diff --git a/.env.example b/.env.example index 12b23378378..c9d61d23e59 100644 --- a/.env.example +++ b/.env.example @@ -945,4 +945,10 @@ ARBITRAGE_EVM_PRIVATE_KEY= # Private key for the wallet executi FLASHBOTS_RELAY_SIGNING_KEY= # Signing key for Flashbots relay interactions BUNDLE_EXECUTOR_ADDRESS= # Address of the bundle executor contract - +# EigenDA Configuration +EVM_PRIVATE_KEY= +BASE_RPC_URL=https://base.drpc.org +# Optional: Default identifier to use for all operations (must be hex-encoded) +# If not provided, will use existing identifier or create a new one +# Example: 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef +EIGENDA_IDENTIFIER= diff --git a/agent/package.json b/agent/package.json index 87e92ac76b1..560d0ca7052 100644 --- a/agent/package.json +++ b/agent/package.json @@ -150,6 +150,7 @@ "@elizaos/plugin-zilliqa": "workspace:*", "@elizaos/client-deva": "workspace:*", "@elizaos/plugin-arbitrage": "workspace:*", + "@elizaos/plugin-eigenda": "workspace:*", "readline": "1.3.0", "ws": "8.18.0", "yargs": "17.7.2" diff --git a/agent/src/index.ts b/agent/src/index.ts index 2a4cc1c0a58..89d1a4e1436 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -137,6 +137,12 @@ import { nvidiaNimPlugin } from "@elizaos/plugin-nvidia-nim"; import { zxPlugin } from "@elizaos/plugin-0x"; import { hyperbolicPlugin } from "@elizaos/plugin-hyperbolic"; import { litPlugin } from "@elizaos/plugin-lit"; +import { OpacityAdapter } from "@elizaos/plugin-opacity"; +import { openWeatherPlugin } from "@elizaos/plugin-open-weather"; +import { stargazePlugin } from "@elizaos/plugin-stargaze"; +import { akashPlugin } from "@elizaos/plugin-akash"; +import { quaiPlugin } from "@elizaos/plugin-quai"; +import { eigendaPlugin } from "@elizaos/plugin-eigenda"; import Database from "better-sqlite3"; import fs from "fs"; import net from "net"; @@ -914,6 +920,18 @@ export async function initializeClients( } function getSecret(character: Character, secret: string) { + // Special handling for EigenDA secrets + if (secret === "EIGENDA_PRIVATE_KEY") { + return character.settings?.secrets?.EIGENDA_PRIVATE_KEY || + character.settings?.secrets?.EVM_PRIVATE_KEY || + process.env.EIGENDA_PRIVATE_KEY || + process.env.EVM_PRIVATE_KEY; + } + if (secret === "BASE_RPC_URL") { + return character.settings?.secrets?.BASE_RPC_URL || + process.env.BASE_RPC_URL || + "https://base.drpc.org"; + } return character.settings?.secrets?.[secret] || process.env[secret]; } @@ -984,6 +1002,7 @@ export async function createAgent( opacityProverUrl: process.env.OPACITY_PROVER_URL, modelProvider: character.modelProvider, token: token, + eigenDAPrivateKey: process.env.EIGENDA_PRIVATE_KEY, }); elizaLogger.log("Verifiable inference adapter initialized"); elizaLogger.log("teamId", process.env.OPACITY_TEAM_ID); @@ -1294,6 +1313,10 @@ export async function createAgent( getSecret(character, "ARBITRAGE_BUNDLE_EXECUTOR_ADDRESS") ? arbitragePlugin : null, + getSecret(character, "EIGENDA_PRIVATE_KEY") && + getSecret(character, "BASE_RPC_URL") + ? eigendaPlugin + : null, ] .flat() .filter(Boolean), diff --git a/client/src/lib/info.json b/client/src/lib/info.json index 18f2047dcae..1023abca0a9 100644 --- a/client/src/lib/info.json +++ b/client/src/lib/info.json @@ -1 +1 @@ -{"version": "0.1.9-alpha.1"} +{"version": "0.1.9"} diff --git a/packages/plugin-eigenda/.npmignore b/packages/plugin-eigenda/.npmignore new file mode 100644 index 00000000000..078562eceab --- /dev/null +++ b/packages/plugin-eigenda/.npmignore @@ -0,0 +1,6 @@ +* + +!dist/** +!package.json +!readme.md +!tsup.config.ts \ No newline at end of file diff --git a/packages/plugin-eigenda/README.md b/packages/plugin-eigenda/README.md new file mode 100644 index 00000000000..2744bdc7068 --- /dev/null +++ b/packages/plugin-eigenda/README.md @@ -0,0 +1,167 @@ +# @elizaos/plugin-eigenda - EigenDA Plugin for Eliza + +The EigenDA plugin enables interaction with EigenDA's data availability layer through Eliza. It provides functionality for uploading data, retrieving data, and checking upload status on the EigenDA network. + +## Features + +- Upload data to EigenDA network +- Retrieve data using job ID, request ID, or batch header hash + blob index +- Check upload status +- Automatic identifier management +- Automatic balance monitoring and top-up +- Support for text, JSON, and binary data + +## Installation + +```bash +npm install @elizaos/plugin-eigenda +``` + +## Configuration + +The plugin requires certain environment variables to be set. You can set these in your `.env` file or through your runtime environment: + +```env +# Required +EVM_PRIVATE_KEY=your_private_key + +# Optional (defaults provided) +API_URL=http://3.220.4.143:5000 +BASE_RPC_URL=https://base.drpc.org +CREDITS_CONTRACT_ADDRESS=0x0CC001F1bDe9cd129092d4d24D935DB985Ce42A9 +EIGENDA_IDENTIFIER=your_hex_identifier # Optional: Use a specific identifier for all operations +``` + +### Environment Variables + +| Variable | Required | Default | Description | +|----------|----------|---------|-------------| +| `EVM_PRIVATE_KEY` | Yes | - | Private key for signing transactions | +| `API_URL` | No | `http://3.220.4.143:5000` | EigenDA API endpoint | +| `BASE_RPC_URL` | No | `https://base.drpc.org` | Base network RPC URL | +| `CREDITS_CONTRACT_ADDRESS` | No | `0x0CC001F1bDe9cd129092d4d24D935DB985Ce42A9` | Credits contract address on Base | +| `EIGENDA_IDENTIFIER` | No | - | Hex-encoded identifier to use for all operations | + +## Usage + +### Uploading Data + +```typescript +// Upload text data +await runtime.execute("UPLOAD_DATA", { + content: "Hello, EigenDA!" +}); + +// Upload JSON data +await runtime.execute("UPLOAD_DATA", { + content: JSON.stringify({ + name: "Test Object", + values: [1, 2, 3] + }) +}); + +// Upload with specific identifier (overrides EIGENDA_IDENTIFIER from env) +await runtime.execute("UPLOAD_DATA", { + content: "Hello, EigenDA!", + identifier: "0x1234567890abcdef" +}); +``` + +### Checking Status + +```typescript +await runtime.execute("GET_STATUS", { + jobId: "abc123def456" +}); +``` + +### Retrieving Data + +```typescript +// Retrieve by job ID +await runtime.execute("RETRIEVE_DATA", { + jobId: "abc123def456" +}); + +// Retrieve by request ID +await runtime.execute("RETRIEVE_DATA", { + requestId: "xyz789" +}); + +// Retrieve by batch header hash and blob index +await runtime.execute("RETRIEVE_DATA", { + batchHeaderHash: "0xabcdef...", + blobIndex: 0 +}); +``` + +## Important Notes + +1. **Processing Time**: Data uploads typically require 5-10 minutes of processing time before they are available for retrieval. + +2. **Balance Management**: The plugin automatically checks your balance and tops up with 0.01 ETH if it falls below the threshold. + +3. **Identifiers**: The plugin handles identifiers in the following priority: + - Uses identifier provided in the action call if specified + - Uses `EIGENDA_IDENTIFIER` from environment if set + - Uses an existing identifier from the account if available + - Creates a new identifier if none exists + +4. **Data Types**: The plugin supports: + - Text data + - JSON data (automatically stringified) + - Binary data + +## Example Workflow + +```typescript +// 1. Upload data +const uploadResult = await runtime.execute("UPLOAD_DATA", { + content: "Hello, EigenDA!" +}); +const jobId = uploadResult.content.job_id; + +// 2. Check status +await runtime.execute("GET_STATUS", { + jobId +}); + +// 3. Retrieve data (after processing is complete) +await runtime.execute("RETRIEVE_DATA", { + jobId +}); +``` + +## Error Handling + +The plugin includes comprehensive error handling for: +- Invalid configuration +- Network issues +- Insufficient balance +- Invalid data formats +- Failed uploads/retrievals + +Error messages are descriptive and include specific details about what went wrong. + +## Development + +### Building + +```bash +npm run build +``` + +### Testing + +```bash +npm test +``` + +## Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +## Support + +For support, please open an issue in the repository or contact the EigenDA team. + diff --git a/packages/plugin-eigenda/eslint.config.mjs b/packages/plugin-eigenda/eslint.config.mjs new file mode 100644 index 00000000000..92fe5bbebef --- /dev/null +++ b/packages/plugin-eigenda/eslint.config.mjs @@ -0,0 +1,3 @@ +import eslintGlobalConfig from "../../eslint.config.mjs"; + +export default [...eslintGlobalConfig]; diff --git a/packages/plugin-eigenda/package.json b/packages/plugin-eigenda/package.json new file mode 100644 index 00000000000..1c14ea80df9 --- /dev/null +++ b/packages/plugin-eigenda/package.json @@ -0,0 +1,39 @@ +{ + "name": "@elizaos/plugin-eigenda", + "version": "0.1.0", + "description": "EigenDA plugin for Eliza", + "type": "module", + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsup", + "dev": "tsup --watch", + "clean": "rimraf dist", + "typecheck": "tsc --noEmit", + "lint": "eslint src/", + "lint:fix": "eslint src/ --fix" + }, + "dependencies": { + "@elizaos/core": "workspace:*", + "ethers": "^6.11.1", + "axios": "^1.6.7", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/node": "^20.11.19", + "rimraf": "^5.0.5", + "tsup": "^8.0.2", + "typescript": "^5.3.3" + } +} diff --git a/packages/plugin-eigenda/src/abi/Credits.json b/packages/plugin-eigenda/src/abi/Credits.json new file mode 100644 index 00000000000..cd7b8169998 --- /dev/null +++ b/packages/plugin-eigenda/src/abi/Credits.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"balances","inputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"batchDeduct","inputs":[{"name":"identifiers","type":"bytes32[]","internalType":"bytes32[]"},{"name":"bytesUsed","type":"uint256[]","internalType":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"createIdentifier","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"nonpayable"},{"type":"function","name":"getBalance","inputs":[{"name":"identifier","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getIdentifierOwner","inputs":[{"name":"identifier","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getProxyRewards","inputs":[{"name":"proxy","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getUserIdentifierAt","inputs":[{"name":"user","type":"address","internalType":"address"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getUserIdentifierCount","inputs":[{"name":"user","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getUserIdentifiers","inputs":[{"name":"user","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bytes32[]","internalType":"bytes32[]"}],"stateMutability":"view"},{"type":"function","name":"identifierOwners","inputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"_owner","type":"address","internalType":"address"},{"name":"_pricePerGB","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isProxy","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pricePerGB","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"proxiableUUID","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"proxyRewards","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setPricePerGB","inputs":[{"name":"newPrice","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setProxy","inputs":[{"name":"proxy","type":"address","internalType":"address"},{"name":"authorized","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"topup","inputs":[{"name":"identifier","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"transferIdentifier","inputs":[{"name":"identifier","type":"bytes32","internalType":"bytes32"},{"name":"to","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"upgradeTo","inputs":[{"name":"newImplementation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"upgradeToAndCall","inputs":[{"name":"newImplementation","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"userIdentifiers","inputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"withdrawRewards","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"AdminChanged","inputs":[{"name":"previousAdmin","type":"address","indexed":false,"internalType":"address"},{"name":"newAdmin","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"BatchDeduct","inputs":[{"name":"identifiers","type":"bytes32[]","indexed":false,"internalType":"bytes32[]"},{"name":"bytesUsed","type":"uint256[]","indexed":false,"internalType":"uint256[]"}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"name":"beacon","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"IdentifierCreated","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"identifier","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"IdentifierTransfer","inputs":[{"name":"identifier","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"owner","type":"address","indexed":false,"internalType":"address"},{"name":"pricePerGB","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint8","indexed":false,"internalType":"uint8"}],"anonymous":false},{"type":"event","name":"PriceUpdate","inputs":[{"name":"oldPrice","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newPrice","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"RewardsWithdrawn","inputs":[{"name":"proxy","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TopUp","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"identifier","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"name":"implementation","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"ArrayLengthMismatch","inputs":[]},{"type":"error","name":"InsufficientBalance","inputs":[]},{"type":"error","name":"InvalidAddress","inputs":[]},{"type":"error","name":"InvalidAmount","inputs":[]},{"type":"error","name":"NoIdentifier","inputs":[]},{"type":"error","name":"NotIdentifierOwner","inputs":[]},{"type":"error","name":"TransferFailed","inputs":[]},{"type":"error","name":"Unauthorized","inputs":[]},{"type":"error","name":"ZeroAddress","inputs":[]}],"bytecode":{"object":"0x60a06040523060805234801561001457600080fd5b5061001d610022565b6100e1565b600054610100900460ff161561008e5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146100df576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051611ac1610118600039600081816105e801528181610631015281816106d001528181610710015261081f0152611ac16000f3fe60806040526004361061014b5760003560e01c80638da5cb5b116100b6578063cd6dc6871161006f578063cd6dc68714610403578063d4284d2714610423578063d56cc9fc14610443578063e35ce0bb14610479578063e9af001f14610499578063ffeb7561146104ae57600080fd5b80638da5cb5b146103275780638e739461146103475780639c65d66714610374578063af3a312d146103a1578063b7f12f26146103c1578063c7b8981c146103ee57600080fd5b80634f1ef286116101085780634f1ef2861461025c57806351a39a581461026f57806352d1902d1461028f5780636289ea64146102a457806383e9724a146102c45780638909aa3f146102fa57600080fd5b80631cf308411461015057806329710388146101795780632bc73c06146101b957806330433e33146101ce57806335fe94ee1461021c5780633659cfe61461023c575b600080fd5b34801561015c57600080fd5b50610166606a5481565b6040519081526020015b60405180910390f35b34801561018557600080fd5b506101a9610194366004611568565b60686020526000908152604090205460ff1681565b6040519015158152602001610170565b6101cc6101c7366004611583565b6104e4565b005b3480156101da57600080fd5b506102046101e9366004611583565b6000908152606660205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610170565b34801561022857600080fd5b5061016661023736600461159c565b6105ad565b34801561024857600080fd5b506101cc610257366004611568565b6105de565b6101cc61026a3660046115dc565b6106c6565b34801561027b57600080fd5b506101cc61028a36600461169e565b610796565b34801561029b57600080fd5b50610166610812565b3480156102b057600080fd5b506101cc6102bf3660046116da565b6108c5565b3480156102d057600080fd5b506101666102df366004611568565b6001600160a01b031660009081526067602052604090205490565b34801561030657600080fd5b50610166610315366004611583565b60656020526000908152604090205481565b34801561033357600080fd5b50606b54610204906001600160a01b031681565b34801561035357600080fd5b50610166610362366004611583565b60009081526065602052604090205490565b34801561038057600080fd5b5061039461038f366004611568565b610a5f565b6040516101709190611706565b3480156103ad57600080fd5b506101666103bc36600461159c565b610acb565b3480156103cd57600080fd5b506101666103dc366004611568565b60696020526000908152604090205481565b3480156103fa57600080fd5b506101cc610b66565b34801561040f57600080fd5b506101cc61041e36600461159c565b610c77565b34801561042f57600080fd5b506101cc61043e366004611796565b610e33565b34801561044f57600080fd5b5061020461045e366004611583565b6066602052600090815260409020546001600160a01b031681565b34801561048557600080fd5b506101cc610494366004611583565b610fde565b3480156104a557600080fd5b5061016661106e565b3480156104ba57600080fd5b506101666104c9366004611568565b6001600160a01b031660009081526069602052604090205490565b346000036105055760405163162908e360e11b815260040160405180910390fd5b806105195761051261106e565b9050610550565b6000818152606660205260409020546001600160a01b03163314610550576040516308baca6360e41b815260040160405180910390fd5b6000818152606560205260408120805434929061056e908490611818565b9091555050604051348152819033907fea2cc5695dc559d82fa71cb78973fb4c48532b3ec451e3cd5e8a7f26901ba96b9060200160405180910390a350565b606760205281600052604060002081815481106105c957600080fd5b90600052602060002001600091509150505481565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361062f5760405162461bcd60e51b81526004016106269061182b565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610678600080516020611a45833981519152546001600160a01b031690565b6001600160a01b03161461069e5760405162461bcd60e51b815260040161062690611877565b6106a7816110f4565b604080516000808252602082019092526106c39183919061111e565b50565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361070e5760405162461bcd60e51b81526004016106269061182b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610757600080516020611a45833981519152546001600160a01b031690565b6001600160a01b03161461077d5760405162461bcd60e51b815260040161062690611877565b610786826110f4565b6107928282600161111e565b5050565b606b546001600160a01b031633146107c0576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0382166107e75760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b03919091166000908152606860205260409020805460ff1916911515919091179055565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108b25760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610626565b50600080516020611a4583398151915290565b6000828152606660205260409020546001600160a01b031633146108fc576040516308baca6360e41b815260040160405180910390fd5b6001600160a01b0381166109235760405163d92e233d60e01b815260040160405180910390fd5b336000908152606760205260408120905b81548110156109e85783828281548110610950576109506118c3565b9060005260206000200154036109d65781548290610970906001906118d9565b81548110610980576109806118c3565b906000526020600020015482828154811061099d5761099d6118c3565b9060005260206000200181905550818054806109bb576109bb6118ec565b600190038181906000526020600020016000905590556109e8565b806109e081611902565b915050610934565b506001600160a01b0382166000818152606760209081526040808320805460018101825590845282842001879055868352606690915280822080546001600160a01b0319168417905551339186917f488d8edd8c226bb2be5387f47cc947711499bfce8fe52bb568d24ab5048ef4489190a4505050565b6001600160a01b038116600090815260676020908152604091829020805483518184028101840190945280845260609392830182828015610abf57602002820191906000526020600020905b815481526020019060010190808311610aab575b50505050509050919050565b6001600160a01b0382166000908152606760205260408120548210610b285760405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606401610626565b6001600160a01b0383166000908152606760205260409020805483908110610b5257610b526118c3565b906000526020600020015490505b92915050565b3360009081526068602052604090205460ff16610b95576040516282b42960e81b815260040160405180910390fd5b3360009081526069602052604081205490819003610bc65760405163162908e360e11b815260040160405180910390fd5b336000818152606960205260408082208290555190919083908381818185875af1925050503d8060008114610c17576040519150601f19603f3d011682016040523d82523d6000602084013e610c1c565b606091505b5050905080610c3e576040516312171d8360e31b815260040160405180910390fd5b60405182815233907f8a43c4352486ec339f487f64af78ca5cbf06cd47833f073d3baf3a193e5031619060200160405180910390a25050565b600054610100900460ff1615808015610c975750600054600160ff909116105b80610cb15750303b158015610cb1575060005460ff166001145b610d145760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610626565b6000805460ff191660011790558015610d37576000805461ff0019166101001790555b6001600160a01b038316610d5e5760405163d92e233d60e01b815260040160405180910390fd5b81600003610d7f5760405163162908e360e11b815260040160405180910390fd5b610d87611289565b606b80546001600160a01b0319166001600160a01b038516908117909155606a8390556001606c5560408051918252602082018490527f25ff68dd81b34665b5ba7e553ee5511bf6812e12adb4a7e2c0d9e26b3099ce79910160405180910390a18015610e2e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b3360009081526068602052604090205460ff16610e62576040516282b42960e81b815260040160405180910390fd5b828114610e825760405163512509d360e11b815260040160405180910390fd5b6000805b84811015610f745760006340000000606a54868685818110610eaa57610eaa6118c3565b90506020020135610ebb919061191b565b610ec59190611932565b90508060656000898986818110610ede57610ede6118c3565b905060200201358152602001908152602001600020541015610f1357604051631e9acf1760e31b815260040160405180910390fd5b8060656000898986818110610f2a57610f2a6118c3565b9050602002013581526020019081526020016000206000828254610f4e91906118d9565b90915550610f5e90508184611818565b9250508080610f6c90611902565b915050610e86565b503360009081526069602052604081208054839290610f94908490611818565b90915550506040517f95c47b4d1e02d4dabb621aebe7d32cb836a3add7ea736ec8940515d7d2e4ff5490610fcf908790879087908790611986565b60405180910390a15050505050565b606b546001600160a01b03163314611008576040516282b42960e81b815260040160405180910390fd5b806000036110295760405163162908e360e11b815260040160405180910390fd5b606a80549082905560408051828152602081018490527f92664190cca12aca9cd5309d87194bdda75bb51362d71c06e1a6f75c7c765711910160405180910390a15050565b606c80546000918291908261108283611902565b90915550336000818152606760209081526040808320805460018101825590845282842001859055848352606690915280822080546001600160a01b031916841790555192935083927f1955e31a47520cb5353f8c2b04c3bf2d8dd6cf0fbe5d983ed8040e69c665fb889190a3919050565b606b546001600160a01b031633146106c3576040516282b42960e81b815260040160405180910390fd5b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561115157610e2e836112f6565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111ab575060408051601f3d908101601f191682019092526111a8918101906119b8565b60015b61120e5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610626565b600080516020611a45833981519152811461127d5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610626565b50610e2e838383611392565b600054610100900460ff166112f45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610626565b565b6001600160a01b0381163b6113635760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610626565b600080516020611a4583398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61139b836113bd565b6000825111806113a85750805b15610e2e576113b783836113fd565b50505050565b6113c6816112f6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606114228383604051806060016040528060278152602001611a6560279139611429565b9392505050565b6060600080856001600160a01b03168560405161144691906119f5565b600060405180830381855af49150503d8060008114611481576040519150601f19603f3d011682016040523d82523d6000602084013e611486565b606091505b5091509150611497868383876114a1565b9695505050505050565b60608315611510578251600003611509576001600160a01b0385163b6115095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610626565b508161151a565b61151a8383611522565b949350505050565b8151156115325781518083602001fd5b8060405162461bcd60e51b81526004016106269190611a11565b80356001600160a01b038116811461156357600080fd5b919050565b60006020828403121561157a57600080fd5b6114228261154c565b60006020828403121561159557600080fd5b5035919050565b600080604083850312156115af57600080fd5b6115b88361154c565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156115ef57600080fd5b6115f88361154c565b9150602083013567ffffffffffffffff8082111561161557600080fd5b818501915085601f83011261162957600080fd5b81358181111561163b5761163b6115c6565b604051601f8201601f19908116603f01168101908382118183101715611663576116636115c6565b8160405282815288602084870101111561167c57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600080604083850312156116b157600080fd5b6116ba8361154c565b9150602083013580151581146116cf57600080fd5b809150509250929050565b600080604083850312156116ed57600080fd5b823591506116fd6020840161154c565b90509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561173e57835183529284019291840191600101611722565b50909695505050505050565b60008083601f84011261175c57600080fd5b50813567ffffffffffffffff81111561177457600080fd5b6020830191508360208260051b850101111561178f57600080fd5b9250929050565b600080600080604085870312156117ac57600080fd5b843567ffffffffffffffff808211156117c457600080fd5b6117d08883890161174a565b909650945060208701359150808211156117e957600080fd5b506117f68782880161174a565b95989497509550505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610b6057610b60611802565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b81810381811115610b6057610b60611802565b634e487b7160e01b600052603160045260246000fd5b60006001820161191457611914611802565b5060010190565b8082028115828204841417610b6057610b60611802565b60008261194f57634e487b7160e01b600052601260045260246000fd5b500490565b81835260006001600160fb1b0383111561196d57600080fd5b8260051b80836020870137939093016020019392505050565b60408152600061199a604083018688611954565b82810360208401526119ad818587611954565b979650505050505050565b6000602082840312156119ca57600080fd5b5051919050565b60005b838110156119ec5781810151838201526020016119d4565b50506000910152565b60008251611a078184602087016119d1565b9190910192915050565b6020815260008251806020840152611a308160408501602087016119d1565b601f01601f1916919091016040019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212203de3c74340dfcc3692ec03df7309c5097cf5811f3a65f7c32126d95c330fd32b64736f6c63430008130033","sourceMap":"264:5997:37:-:0;;;1332:4:24;1289:48;;1611:53:37;;;;;;;;;-1:-1:-1;1635:22:37;:20;:22::i;:::-;264:5997;;5939:280:23;6007:13;;;;;;;6006:14;5998:66;;;;-1:-1:-1;;;5998:66:23;;216:2:40;5998:66:23;;;198:21:40;255:2;235:18;;;228:30;294:34;274:18;;;267:62;-1:-1:-1;;;345:18:40;;;338:37;392:19;;5998:66:23;;;;;;;;6078:12;;6094:15;6078:12;;;:31;6074:139;;6125:12;:30;;-1:-1:-1;;6125:30:23;6140:15;6125:30;;;;;;6174:28;;564:36:40;;;6174:28:23;;552:2:40;537:18;6174:28:23;;;;;;;6074:139;5939:280::o;422:184:40:-;264:5997:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x60806040526004361061014b5760003560e01c80638da5cb5b116100b6578063cd6dc6871161006f578063cd6dc68714610403578063d4284d2714610423578063d56cc9fc14610443578063e35ce0bb14610479578063e9af001f14610499578063ffeb7561146104ae57600080fd5b80638da5cb5b146103275780638e739461146103475780639c65d66714610374578063af3a312d146103a1578063b7f12f26146103c1578063c7b8981c146103ee57600080fd5b80634f1ef286116101085780634f1ef2861461025c57806351a39a581461026f57806352d1902d1461028f5780636289ea64146102a457806383e9724a146102c45780638909aa3f146102fa57600080fd5b80631cf308411461015057806329710388146101795780632bc73c06146101b957806330433e33146101ce57806335fe94ee1461021c5780633659cfe61461023c575b600080fd5b34801561015c57600080fd5b50610166606a5481565b6040519081526020015b60405180910390f35b34801561018557600080fd5b506101a9610194366004611568565b60686020526000908152604090205460ff1681565b6040519015158152602001610170565b6101cc6101c7366004611583565b6104e4565b005b3480156101da57600080fd5b506102046101e9366004611583565b6000908152606660205260409020546001600160a01b031690565b6040516001600160a01b039091168152602001610170565b34801561022857600080fd5b5061016661023736600461159c565b6105ad565b34801561024857600080fd5b506101cc610257366004611568565b6105de565b6101cc61026a3660046115dc565b6106c6565b34801561027b57600080fd5b506101cc61028a36600461169e565b610796565b34801561029b57600080fd5b50610166610812565b3480156102b057600080fd5b506101cc6102bf3660046116da565b6108c5565b3480156102d057600080fd5b506101666102df366004611568565b6001600160a01b031660009081526067602052604090205490565b34801561030657600080fd5b50610166610315366004611583565b60656020526000908152604090205481565b34801561033357600080fd5b50606b54610204906001600160a01b031681565b34801561035357600080fd5b50610166610362366004611583565b60009081526065602052604090205490565b34801561038057600080fd5b5061039461038f366004611568565b610a5f565b6040516101709190611706565b3480156103ad57600080fd5b506101666103bc36600461159c565b610acb565b3480156103cd57600080fd5b506101666103dc366004611568565b60696020526000908152604090205481565b3480156103fa57600080fd5b506101cc610b66565b34801561040f57600080fd5b506101cc61041e36600461159c565b610c77565b34801561042f57600080fd5b506101cc61043e366004611796565b610e33565b34801561044f57600080fd5b5061020461045e366004611583565b6066602052600090815260409020546001600160a01b031681565b34801561048557600080fd5b506101cc610494366004611583565b610fde565b3480156104a557600080fd5b5061016661106e565b3480156104ba57600080fd5b506101666104c9366004611568565b6001600160a01b031660009081526069602052604090205490565b346000036105055760405163162908e360e11b815260040160405180910390fd5b806105195761051261106e565b9050610550565b6000818152606660205260409020546001600160a01b03163314610550576040516308baca6360e41b815260040160405180910390fd5b6000818152606560205260408120805434929061056e908490611818565b9091555050604051348152819033907fea2cc5695dc559d82fa71cb78973fb4c48532b3ec451e3cd5e8a7f26901ba96b9060200160405180910390a350565b606760205281600052604060002081815481106105c957600080fd5b90600052602060002001600091509150505481565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361062f5760405162461bcd60e51b81526004016106269061182b565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610678600080516020611a45833981519152546001600160a01b031690565b6001600160a01b03161461069e5760405162461bcd60e51b815260040161062690611877565b6106a7816110f4565b604080516000808252602082019092526106c39183919061111e565b50565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361070e5760405162461bcd60e51b81526004016106269061182b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610757600080516020611a45833981519152546001600160a01b031690565b6001600160a01b03161461077d5760405162461bcd60e51b815260040161062690611877565b610786826110f4565b6107928282600161111e565b5050565b606b546001600160a01b031633146107c0576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0382166107e75760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b03919091166000908152606860205260409020805460ff1916911515919091179055565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108b25760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610626565b50600080516020611a4583398151915290565b6000828152606660205260409020546001600160a01b031633146108fc576040516308baca6360e41b815260040160405180910390fd5b6001600160a01b0381166109235760405163d92e233d60e01b815260040160405180910390fd5b336000908152606760205260408120905b81548110156109e85783828281548110610950576109506118c3565b9060005260206000200154036109d65781548290610970906001906118d9565b81548110610980576109806118c3565b906000526020600020015482828154811061099d5761099d6118c3565b9060005260206000200181905550818054806109bb576109bb6118ec565b600190038181906000526020600020016000905590556109e8565b806109e081611902565b915050610934565b506001600160a01b0382166000818152606760209081526040808320805460018101825590845282842001879055868352606690915280822080546001600160a01b0319168417905551339186917f488d8edd8c226bb2be5387f47cc947711499bfce8fe52bb568d24ab5048ef4489190a4505050565b6001600160a01b038116600090815260676020908152604091829020805483518184028101840190945280845260609392830182828015610abf57602002820191906000526020600020905b815481526020019060010190808311610aab575b50505050509050919050565b6001600160a01b0382166000908152606760205260408120548210610b285760405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606401610626565b6001600160a01b0383166000908152606760205260409020805483908110610b5257610b526118c3565b906000526020600020015490505b92915050565b3360009081526068602052604090205460ff16610b95576040516282b42960e81b815260040160405180910390fd5b3360009081526069602052604081205490819003610bc65760405163162908e360e11b815260040160405180910390fd5b336000818152606960205260408082208290555190919083908381818185875af1925050503d8060008114610c17576040519150601f19603f3d011682016040523d82523d6000602084013e610c1c565b606091505b5050905080610c3e576040516312171d8360e31b815260040160405180910390fd5b60405182815233907f8a43c4352486ec339f487f64af78ca5cbf06cd47833f073d3baf3a193e5031619060200160405180910390a25050565b600054610100900460ff1615808015610c975750600054600160ff909116105b80610cb15750303b158015610cb1575060005460ff166001145b610d145760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610626565b6000805460ff191660011790558015610d37576000805461ff0019166101001790555b6001600160a01b038316610d5e5760405163d92e233d60e01b815260040160405180910390fd5b81600003610d7f5760405163162908e360e11b815260040160405180910390fd5b610d87611289565b606b80546001600160a01b0319166001600160a01b038516908117909155606a8390556001606c5560408051918252602082018490527f25ff68dd81b34665b5ba7e553ee5511bf6812e12adb4a7e2c0d9e26b3099ce79910160405180910390a18015610e2e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b3360009081526068602052604090205460ff16610e62576040516282b42960e81b815260040160405180910390fd5b828114610e825760405163512509d360e11b815260040160405180910390fd5b6000805b84811015610f745760006340000000606a54868685818110610eaa57610eaa6118c3565b90506020020135610ebb919061191b565b610ec59190611932565b90508060656000898986818110610ede57610ede6118c3565b905060200201358152602001908152602001600020541015610f1357604051631e9acf1760e31b815260040160405180910390fd5b8060656000898986818110610f2a57610f2a6118c3565b9050602002013581526020019081526020016000206000828254610f4e91906118d9565b90915550610f5e90508184611818565b9250508080610f6c90611902565b915050610e86565b503360009081526069602052604081208054839290610f94908490611818565b90915550506040517f95c47b4d1e02d4dabb621aebe7d32cb836a3add7ea736ec8940515d7d2e4ff5490610fcf908790879087908790611986565b60405180910390a15050505050565b606b546001600160a01b03163314611008576040516282b42960e81b815260040160405180910390fd5b806000036110295760405163162908e360e11b815260040160405180910390fd5b606a80549082905560408051828152602081018490527f92664190cca12aca9cd5309d87194bdda75bb51362d71c06e1a6f75c7c765711910160405180910390a15050565b606c80546000918291908261108283611902565b90915550336000818152606760209081526040808320805460018101825590845282842001859055848352606690915280822080546001600160a01b031916841790555192935083927f1955e31a47520cb5353f8c2b04c3bf2d8dd6cf0fbe5d983ed8040e69c665fb889190a3919050565b606b546001600160a01b031633146106c3576040516282b42960e81b815260040160405180910390fd5b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561115157610e2e836112f6565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111ab575060408051601f3d908101601f191682019092526111a8918101906119b8565b60015b61120e5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610626565b600080516020611a45833981519152811461127d5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610626565b50610e2e838383611392565b600054610100900460ff166112f45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610626565b565b6001600160a01b0381163b6113635760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610626565b600080516020611a4583398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61139b836113bd565b6000825111806113a85750805b15610e2e576113b783836113fd565b50505050565b6113c6816112f6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606114228383604051806060016040528060278152602001611a6560279139611429565b9392505050565b6060600080856001600160a01b03168560405161144691906119f5565b600060405180830381855af49150503d8060008114611481576040519150601f19603f3d011682016040523d82523d6000602084013e611486565b606091505b5091509150611497868383876114a1565b9695505050505050565b60608315611510578251600003611509576001600160a01b0385163b6115095760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610626565b508161151a565b61151a8383611522565b949350505050565b8151156115325781518083602001fd5b8060405162461bcd60e51b81526004016106269190611a11565b80356001600160a01b038116811461156357600080fd5b919050565b60006020828403121561157a57600080fd5b6114228261154c565b60006020828403121561159557600080fd5b5035919050565b600080604083850312156115af57600080fd5b6115b88361154c565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156115ef57600080fd5b6115f88361154c565b9150602083013567ffffffffffffffff8082111561161557600080fd5b818501915085601f83011261162957600080fd5b81358181111561163b5761163b6115c6565b604051601f8201601f19908116603f01168101908382118183101715611663576116636115c6565b8160405282815288602084870101111561167c57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600080604083850312156116b157600080fd5b6116ba8361154c565b9150602083013580151581146116cf57600080fd5b809150509250929050565b600080604083850312156116ed57600080fd5b823591506116fd6020840161154c565b90509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561173e57835183529284019291840191600101611722565b50909695505050505050565b60008083601f84011261175c57600080fd5b50813567ffffffffffffffff81111561177457600080fd5b6020830191508360208260051b850101111561178f57600080fd5b9250929050565b600080600080604085870312156117ac57600080fd5b843567ffffffffffffffff808211156117c457600080fd5b6117d08883890161174a565b909650945060208701359150808211156117e957600080fd5b506117f68782880161174a565b95989497509550505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610b6057610b60611802565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b81810381811115610b6057610b60611802565b634e487b7160e01b600052603160045260246000fd5b60006001820161191457611914611802565b5060010190565b8082028115828204841417610b6057610b60611802565b60008261194f57634e487b7160e01b600052601260045260246000fd5b500490565b81835260006001600160fb1b0383111561196d57600080fd5b8260051b80836020870137939093016020019392505050565b60408152600061199a604083018688611954565b82810360208401526119ad818587611954565b979650505050505050565b6000602082840312156119ca57600080fd5b5051919050565b60005b838110156119ec5781810151838201526020016119d4565b50506000910152565b60008251611a078184602087016119d1565b9190910192915050565b6020815260008251806020840152611a308160408501602087016119d1565b601f01601f1916919091016040019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212203de3c74340dfcc3692ec03df7309c5097cf5811f3a65f7c32126d95c330fd32b64736f6c63430008130033","sourceMap":"264:5997:37:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;655:25;;;;;;;;;;;;;;;;;;;160::40;;;148:2;133:18;655:25:37;;;;;;;;552:39;;;;;;;;;;-1:-1:-1;552:39:37;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;730:14:40;;723:22;705:41;;693:2;678:18;552:39:37;565:187:40;2685:419:37;;;;;;:::i;:::-;;:::i;:::-;;6127:132;;;;;;;;;;-1:-1:-1;6127:132:37;;;;;:::i;:::-;6198:7;6224:28;;;:16;:28;;;;;;-1:-1:-1;;;;;6224:28:37;;6127:132;;;;-1:-1:-1;;;;;1106:32:40;;;1088:51;;1076:2;1061:18;6127:132:37;942:203:40;494:52:37;;;;;;;;;;-1:-1:-1;494:52:37;;;;;:::i;:::-;;:::i;3387:195:24:-;;;;;;;;;;-1:-1:-1;3387:195:24;;;;;:::i;:::-;;:::i;3901:220::-;;;;;;:::i;:::-;;:::i;4974:168:37:-;;;;;;;;;;-1:-1:-1;4974:168:37;;;;;:::i;:::-;;:::i;3006:131:24:-;;;;;;;;;;;;;:::i;4170:798:37:-;;;;;;;;;;-1:-1:-1;4170:798:37;;;;;:::i;:::-;;:::i;5644:130::-;;;;;;;;;;-1:-1:-1;5644:130:37;;;;;:::i;:::-;-1:-1:-1;;;;;5739:21:37;5713:7;5739:21;;;:15;:21;;;;;:28;;5644:130;388:43;;;;;;;;;;-1:-1:-1;388:43:37;;;;;:::i;:::-;;;;;;;;;;;;;;686:20;;;;;;;;;;-1:-1:-1;686:20:37;;;;-1:-1:-1;;;;;686:20:37;;;5388:116;;;;;;;;;;-1:-1:-1;5388:116:37;;;;;:::i;:::-;5451:7;5477:20;;;:8;:20;;;;;;;5388:116;5510:128;;;;;;;;;;-1:-1:-1;5510:128:37;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;5780:220::-;;;;;;;;;;-1:-1:-1;5780:220:37;;;;;:::i;:::-;;:::i;597:47::-;;;;;;;;;;-1:-1:-1;597:47:37;;;;;:::i;:::-;;;;;;;;;;;;;;3777:387;;;;;;;;;;;;;:::i;1670:389::-;;;;;;;;;;-1:-1:-1;1670:389:37;;;;;:::i;:::-;;:::i;3110:661::-;;;;;;;;;;-1:-1:-1;3110:661:37;;;;;:::i;:::-;;:::i;437:51::-;;;;;;;;;;-1:-1:-1;437:51:37;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;437:51:37;;;5148:234;;;;;;;;;;-1:-1:-1;5148:234:37;;;;;:::i;:::-;;:::i;2366:313::-;;;;;;;;;;;;;:::i;6006:115::-;;;;;;;;;;-1:-1:-1;6006:115:37;;;;;:::i;:::-;-1:-1:-1;;;;;6095:19:37;6069:7;6095:19;;;:12;:19;;;;;;;6006:115;2685:419;2751:9;2764:1;2751:14;2747:42;;2774:15;;-1:-1:-1;;;2774:15:37;;;;;;;;;;;2747:42;2803:10;2799:192;;2856:18;:16;:18::i;:::-;2843:31;;2799:192;;;2895:28;;;;:16;:28;;;;;;-1:-1:-1;;;;;2895:28:37;2927:10;2895:42;2891:100;;2960:20;;-1:-1:-1;;;2960:20:37;;;;;;;;;;;2891:100;3009:20;;;;:8;:20;;;;;:33;;3033:9;;3009:20;:33;;3033:9;;3009:33;:::i;:::-;;;;-1:-1:-1;;3057:40:37;;3087:9;160:25:40;;3075:10:37;;3063;;3057:40;;148:2:40;133:18;3057:40:37;;;;;;;2685:419;:::o;494:52::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;3387:195:24:-;-1:-1:-1;;;;;1898:6:24;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:24;;;;;;;:::i;:::-;;;;;;;;;1995:6;-1:-1:-1;;;;;1971:30:24;:20;-1:-1:-1;;;;;;;;;;;1536:65:21;-1:-1:-1;;;;;1536:65:21;;1457:151;1971:20:24;-1:-1:-1;;;;;1971:30:24;;1963:87;;;;-1:-1:-1;;;1963:87:24;;;;;;;:::i;:::-;3468:36:::1;3486:17;3468;:36::i;:::-;3555:12;::::0;;3565:1:::1;3555:12:::0;;;::::1;::::0;::::1;::::0;;;3514:61:::1;::::0;3536:17;;3555:12;3514:21:::1;:61::i;:::-;3387:195:::0;:::o;3901:220::-;-1:-1:-1;;;;;1898:6:24;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:24;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:24;:20;-1:-1:-1;;;;;;;;;;;1536:65:21;-1:-1:-1;;;;;1536:65:21;;1457:151;1971:20:24;-1:-1:-1;;;;;1971:30:24;;1963:87;;;;-1:-1:-1;;;1963:87:24;;;;;;;:::i;:::-;4016:36:::1;4034:17;4016;:36::i;:::-;4062:52;4084:17;4103:4;4109;4062:21;:52::i;:::-;3901:220:::0;;:::o;4974:168:37:-;2204:5;;-1:-1:-1;;;;;2204:5:37;2190:10;:19;2186:46;;2218:14;;-1:-1:-1;;;2218:14:37;;;;;;;;;;;2186:46;-1:-1:-1;;;;;5057:19:37;::::1;5053:45;;5085:13;;-1:-1:-1::0;;;5085:13:37::1;;;;;;;;;;;5053:45;-1:-1:-1::0;;;;;5108:14:37;;;::::1;;::::0;;;:7:::1;:14;::::0;;;;:27;;-1:-1:-1;;5108:27:37::1;::::0;::::1;;::::0;;;::::1;::::0;;4974:168::o;3006:131:24:-;3084:7;2324:4;-1:-1:-1;;;;;2333:6:24;2316:23;;2308:92;;;;-1:-1:-1;;;2308:92:24;;6596:2:40;2308:92:24;;;6578:21:40;6635:2;6615:18;;;6608:30;6674:34;6654:18;;;6647:62;6745:26;6725:18;;;6718:54;6789:19;;2308:92:24;6394:420:40;2308:92:24;-1:-1:-1;;;;;;;;;;;;3006:131:24;:::o;4170:798:37:-;4253:28;;;;:16;:28;;;;;;-1:-1:-1;;;;;4253:28:37;4285:10;4253:42;4249:75;;4304:20;;-1:-1:-1;;;4304:20:37;;;;;;;;;;;4249:75;-1:-1:-1;;;;;4338:16:37;;4334:42;;4363:13;;-1:-1:-1;;;4363:13:37;;;;;;;;;;;4334:42;4489:10;4443:27;4473;;;:15;:27;;;;;;4510:238;4534:16;;4530:20;;4510:238;;;4591:10;4575:9;4585:1;4575:12;;;;;;;;:::i;:::-;;;;;;;;;:26;4571:167;;4646:16;;4636:9;;4646:20;;4665:1;;4646:20;:::i;:::-;4636:31;;;;;;;;:::i;:::-;;;;;;;;;4621:9;4631:1;4621:12;;;;;;;;:::i;:::-;;;;;;;;:46;;;;4685:9;:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4718:5;;4571:167;4552:3;;;;:::i;:::-;;;;4510:238;;;-1:-1:-1;;;;;;4812:19:37;;;;;;:15;:19;;;;;;;;:36;;;;;;;;;;;;;;;;;4858:28;;;:16;:28;;;;;;:33;;-1:-1:-1;;;;;;4858:33:37;;;;;4915:46;4946:10;;4837;;4915:46;;4812:19;4915:46;4239:729;4170:798;;:::o;5510:128::-;-1:-1:-1;;;;;5610:21:37;;;;;;:15;:21;;;;;;;;;5603:28;;;;;;;;;;;;;;;;;5575:16;;5603:28;;;5610:21;5603:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5510:128;;;:::o;5780:220::-;-1:-1:-1;;;;;5896:21:37;;5861:7;5896:21;;;:15;:21;;;;;:28;5888:36;;5880:68;;;;-1:-1:-1;;;5880:68:37;;7558:2:40;5880:68:37;;;7540:21:40;7597:2;7577:18;;;7570:30;-1:-1:-1;;;7616:18:40;;;7609:49;7675:18;;5880:68:37;7356:343:40;5880:68:37;-1:-1:-1;;;;;5965:21:37;;;;;;:15;:21;;;;;:28;;5987:5;;5965:28;;;;;;:::i;:::-;;;;;;;;;5958:35;;5780:220;;;;;:::o;3777:387::-;2308:10;2300:19;;;;:7;:19;;;;;;;;2295:47;;2328:14;;-1:-1:-1;;;2328:14:37;;;;;;;;;;;2295:47;3871:10:::1;3841:14;3858:24:::0;;;:12:::1;:24;::::0;;;;;;3896:11;;;3892:39:::1;;3916:15;;-1:-1:-1::0;;;3916:15:37::1;;;;;;;;;;;3892:39;3963:10;3977:1;3950:24:::0;;;:12:::1;:24;::::0;;;;;:28;;;4016:34;3977:1;;3963:10;4039:6;;3977:1;4016:34;3977:1;4016:34;4039:6;3963:10;4016:34:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3997:53;;;4065:7;4060:37;;4081:16;;-1:-1:-1::0;;;4081:16:37::1;;;;;;;;;;;4060:37;4121:36;::::0;160:25:40;;;4138:10:37::1;::::0;4121:36:::1;::::0;148:2:40;133:18;4121:36:37::1;;;;;;;3831:333;;3777:387::o:0;1670:389::-;3279:19:23;3302:13;;;;;;3301:14;;3347:34;;;;-1:-1:-1;3365:12:23;;3380:1;3365:12;;;;:16;3347:34;3346:108;;;-1:-1:-1;3426:4:23;1713:19:25;:23;;;3387:66:23;;-1:-1:-1;3436:12:23;;;;;:17;3387:66;3325:201;;;;-1:-1:-1;;;3325:201:23;;8116:2:40;3325:201:23;;;8098:21:40;8155:2;8135:18;;;8128:30;8194:34;8174:18;;;8167:62;-1:-1:-1;;;8245:18:40;;;8238:44;8299:19;;3325:201:23;7914:410:40;3325:201:23;3536:12;:16;;-1:-1:-1;;3536:16:23;3551:1;3536:16;;;3562:65;;;;3596:13;:20;;-1:-1:-1;;3596:20:23;;;;;3562:65;-1:-1:-1;;;;;1762:20:37;::::1;1758:46;;1791:13;;-1:-1:-1::0;;;1791:13:37::1;;;;;;;;;;;1758:46;1818:11;1833:1;1818:16:::0;1814:44:::1;;1843:15;;-1:-1:-1::0;;;1843:15:37::1;;;;;;;;;;;1814:44;1877:24;:22;:24::i;:::-;1920:5;:14:::0;;-1:-1:-1;;;;;;1920:14:37::1;-1:-1:-1::0;;;;;1920:14:37;::::1;::::0;;::::1;::::0;;;1944:10:::1;:24:::0;;;-1:-1:-1;1978:14:37::1;:18:::0;2020:32:::1;::::0;;8503:51:40;;;8585:2;8570:18;;8563:34;;;2020:32:37::1;::::0;8476:18:40;2020:32:37::1;;;;;;;3651:14:23::0;3647:99;;;3697:5;3681:21;;-1:-1:-1;;3681:21:23;;;3721:14;;-1:-1:-1;8760:36:40;;3721:14:23;;8748:2:40;8733:18;3721:14:23;;;;;;;3647:99;3269:483;1670:389:37;;:::o;3110:661::-;2308:10;2300:19;;;;:7;:19;;;;;;;;2295:47;;2328:14;;-1:-1:-1;;;2328:14:37;;;;;;;;;;;2295:47;3256:38;;::::1;3252:72;;3303:21;;-1:-1:-1::0;;;3303:21:37::1;;;;;;;;;;;3252:72;3335:19;3373:9:::0;3368:297:::1;3388:22:::0;;::::1;3368:297;;;3431:12;3477:18;3462:10;;3447:9;;3457:1;3447:12;;;;;;;:::i;:::-;;;;;;;:25;;;;:::i;:::-;3446:50;;;;:::i;:::-;3431:65;;3541:4;3514:8;:24;3523:11;;3535:1;3523:14;;;;;;;:::i;:::-;;;;;;;3514:24;;;;;;;;;;;;:31;3510:65;;;3554:21;;-1:-1:-1::0;;;3554:21:37::1;;;;;;;;;;;3510:65;3617:4;3589:8;:24;3598:11;;3610:1;3598:14;;;;;;;:::i;:::-;;;;;;;3589:24;;;;;;;;;;;;:32;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;3635:19:37::1;::::0;-1:-1:-1;3650:4:37;3635:19;::::1;:::i;:::-;;;3417:248;3412:3;;;;;:::i;:::-;;;;3368:297;;;-1:-1:-1::0;3688:10:37::1;3675:24;::::0;;;:12:::1;:24;::::0;;;;:39;;3703:11;;3675:24;:39:::1;::::0;3703:11;;3675:39:::1;:::i;:::-;::::0;;;-1:-1:-1;;3729:35:37::1;::::0;::::1;::::0;::::1;::::0;3741:11;;;;3754:9;;;;3729:35:::1;:::i;:::-;;;;;;;;3242:529;3110:661:::0;;;;:::o;5148:234::-;2204:5;;-1:-1:-1;;;;;2204:5:37;2190:10;:19;2186:46;;2218:14;;-1:-1:-1;;;2218:14:37;;;;;;;;;;;2186:46;5222:8:::1;5234:1;5222:13:::0;5218:41:::1;;5244:15;;-1:-1:-1::0;;;5244:15:37::1;;;;;;;;;;;5218:41;5288:10;::::0;;5308:21;;;;5344:31:::1;::::0;;10216:25:40;;;10272:2;10257:18;;10250:34;;;5344:31:37::1;::::0;10189:18:40;5344:31:37::1;;;;;;;5208:174;5148:234:::0;:::o;2366:313::-;2458:14;:16;;2410:7;;;;2458:16;2410:7;2458:16;;;:::i;:::-;;;;-1:-1:-1;2501:10:37;2450:25;2485:27;;;:15;:27;;;;;;;;:44;;;;;;;;;;;;;;;;;2539:28;;;:16;:28;;;;;;:41;;-1:-1:-1;;;;;;2539:41:37;;;;;2604;2450:25;;-1:-1:-1;2450:25:37;;2604:41;;2450:25;2604:41;2662:10;2366:313;-1:-1:-1;2366:313:37:o;2065:84::-;2204:5;;-1:-1:-1;;;;;2204:5:37;2190:10;:19;2186:46;;2218:14;;-1:-1:-1;;;2218:14:37;;;;;;;;;;;2820:944:21;971:66;3236:59;;;3232:526;;;3311:37;3330:17;3311:18;:37::i;3232:526::-;3412:17;-1:-1:-1;;;;;3383:61:21;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3383:63:21;;;;;;;;-1:-1:-1;;3383:63:21;;;;;;;;;;;;:::i;:::-;;;3379:302;;3610:56;;-1:-1:-1;;;3610:56:21;;10686:2:40;3610:56:21;;;10668:21:40;10725:2;10705:18;;;10698:30;10764:34;10744:18;;;10737:62;-1:-1:-1;;;10815:18:40;;;10808:44;10869:19;;3610:56:21;10484:410:40;3379:302:21;-1:-1:-1;;;;;;;;;;;3496:28:21;;3488:82;;;;-1:-1:-1;;;3488:82:21;;11101:2:40;3488:82:21;;;11083:21:40;11140:2;11120:18;;;11113:30;11179:34;11159:18;;;11152:62;-1:-1:-1;;;11230:18:40;;;11223:39;11279:19;;3488:82:21;10899:405:40;3488:82:21;3447:138;3694:53;3712:17;3731:4;3737:9;3694:17;:53::i;1042:67:24:-;5374:13:23;;;;;;;5366:69;;;;-1:-1:-1;;;5366:69:23;;11511:2:40;5366:69:23;;;11493:21:40;11550:2;11530:18;;;11523:30;11589:34;11569:18;;;11562:62;-1:-1:-1;;;11640:18:40;;;11633:41;11691:19;;5366:69:23;11309:407:40;5366:69:23;1042:67:24:o;1699:281:21:-;-1:-1:-1;;;;;1713:19:25;;;1772:106:21;;;;-1:-1:-1;;;1772:106:21;;11923:2:40;1772:106:21;;;11905:21:40;11962:2;11942:18;;;11935:30;12001:34;11981:18;;;11974:62;-1:-1:-1;;;12052:18:40;;;12045:43;12105:19;;1772:106:21;11721:409:40;1772:106:21;-1:-1:-1;;;;;;;;;;;1888:85:21;;-1:-1:-1;;;;;;1888:85:21;-1:-1:-1;;;;;1888:85:21;;;;;;;;;;1699:281::o;2372:276::-;2480:29;2491:17;2480:10;:29::i;:::-;2537:1;2523:4;:11;:15;:28;;;;2542:9;2523:28;2519:123;;;2567:64;2607:17;2626:4;2567:39;:64::i;:::-;;2372:276;;;:::o;2086:152::-;2152:37;2171:17;2152:18;:37::i;:::-;2204:27;;-1:-1:-1;;;;;2204:27:21;;;;;;;;2086:152;:::o;6685:198:25:-;6768:12;6799:77;6820:6;6828:4;6799:77;;;;;;;;;;;;;;;;;:20;:77::i;:::-;6792:84;6685:198;-1:-1:-1;;;6685:198:25:o;7069:325::-;7210:12;7235;7249:23;7276:6;-1:-1:-1;;;;;7276:19:25;7296:4;7276:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7234:67;;;;7318:69;7345:6;7353:7;7362:10;7374:12;7318:26;:69::i;:::-;7311:76;7069:325;-1:-1:-1;;;;;;7069:325:25:o;7682:628::-;7862:12;7890:7;7886:418;;;7917:10;:17;7938:1;7917:22;7913:286;;-1:-1:-1;;;;;1713:19:25;;;8124:60;;;;-1:-1:-1;;;8124:60:25;;12884:2:40;8124:60:25;;;12866:21:40;12923:2;12903:18;;;12896:30;12962:31;12942:18;;;12935:59;13011:18;;8124:60:25;12682:353:40;8124:60:25;-1:-1:-1;8219:10:25;8212:17;;7886:418;8260:33;8268:10;8280:12;8260:7;:33::i;:::-;7682:628;;;;;;:::o;8832:540::-;8991:17;;:21;8987:379;;9219:10;9213:17;9275:15;9262:10;9258:2;9254:19;9247:44;8987:379;9342:12;9335:20;;-1:-1:-1;;;9335:20:25;;;;;;;;:::i;196:173:40:-;264:20;;-1:-1:-1;;;;;313:31:40;;303:42;;293:70;;359:1;356;349:12;293:70;196:173;;;:::o;374:186::-;433:6;486:2;474:9;465:7;461:23;457:32;454:52;;;502:1;499;492:12;454:52;525:29;544:9;525:29;:::i;757:180::-;816:6;869:2;857:9;848:7;844:23;840:32;837:52;;;885:1;882;875:12;837:52;-1:-1:-1;908:23:40;;757:180;-1:-1:-1;757:180:40:o;1150:254::-;1218:6;1226;1279:2;1267:9;1258:7;1254:23;1250:32;1247:52;;;1295:1;1292;1285:12;1247:52;1318:29;1337:9;1318:29;:::i;:::-;1308:39;1394:2;1379:18;;;;1366:32;;-1:-1:-1;;;1150:254:40:o;1591:127::-;1652:10;1647:3;1643:20;1640:1;1633:31;1683:4;1680:1;1673:15;1707:4;1704:1;1697:15;1723:995;1800:6;1808;1861:2;1849:9;1840:7;1836:23;1832:32;1829:52;;;1877:1;1874;1867:12;1829:52;1900:29;1919:9;1900:29;:::i;:::-;1890:39;;1980:2;1969:9;1965:18;1952:32;2003:18;2044:2;2036:6;2033:14;2030:34;;;2060:1;2057;2050:12;2030:34;2098:6;2087:9;2083:22;2073:32;;2143:7;2136:4;2132:2;2128:13;2124:27;2114:55;;2165:1;2162;2155:12;2114:55;2201:2;2188:16;2223:2;2219;2216:10;2213:36;;;2229:18;;:::i;:::-;2304:2;2298:9;2272:2;2358:13;;-1:-1:-1;;2354:22:40;;;2378:2;2350:31;2346:40;2334:53;;;2402:18;;;2422:22;;;2399:46;2396:72;;;2448:18;;:::i;:::-;2488:10;2484:2;2477:22;2523:2;2515:6;2508:18;2563:7;2558:2;2553;2549;2545:11;2541:20;2538:33;2535:53;;;2584:1;2581;2574:12;2535:53;2640:2;2635;2631;2627:11;2622:2;2614:6;2610:15;2597:46;2685:1;2680:2;2675;2667:6;2663:15;2659:24;2652:35;2706:6;2696:16;;;;;;;1723:995;;;;;:::o;2723:347::-;2788:6;2796;2849:2;2837:9;2828:7;2824:23;2820:32;2817:52;;;2865:1;2862;2855:12;2817:52;2888:29;2907:9;2888:29;:::i;:::-;2878:39;;2967:2;2956:9;2952:18;2939:32;3014:5;3007:13;3000:21;2993:5;2990:32;2980:60;;3036:1;3033;3026:12;2980:60;3059:5;3049:15;;;2723:347;;;;;:::o;3075:254::-;3143:6;3151;3204:2;3192:9;3183:7;3179:23;3175:32;3172:52;;;3220:1;3217;3210:12;3172:52;3256:9;3243:23;3233:33;;3285:38;3319:2;3308:9;3304:18;3285:38;:::i;:::-;3275:48;;3075:254;;;;;:::o;3334:632::-;3505:2;3557:21;;;3627:13;;3530:18;;;3649:22;;;3476:4;;3505:2;3728:15;;;;3702:2;3687:18;;;3476:4;3771:169;3785:6;3782:1;3779:13;3771:169;;;3846:13;;3834:26;;3915:15;;;;3880:12;;;;3807:1;3800:9;3771:169;;;-1:-1:-1;3957:3:40;;3334:632;-1:-1:-1;;;;;;3334:632:40:o;3971:367::-;4034:8;4044:6;4098:3;4091:4;4083:6;4079:17;4075:27;4065:55;;4116:1;4113;4106:12;4065:55;-1:-1:-1;4139:20:40;;4182:18;4171:30;;4168:50;;;4214:1;4211;4204:12;4168:50;4251:4;4243:6;4239:17;4227:29;;4311:3;4304:4;4294:6;4291:1;4287:14;4279:6;4275:27;4271:38;4268:47;4265:67;;;4328:1;4325;4318:12;4265:67;3971:367;;;;;:::o;4343:773::-;4465:6;4473;4481;4489;4542:2;4530:9;4521:7;4517:23;4513:32;4510:52;;;4558:1;4555;4548:12;4510:52;4598:9;4585:23;4627:18;4668:2;4660:6;4657:14;4654:34;;;4684:1;4681;4674:12;4654:34;4723:70;4785:7;4776:6;4765:9;4761:22;4723:70;:::i;:::-;4812:8;;-1:-1:-1;4697:96:40;-1:-1:-1;4900:2:40;4885:18;;4872:32;;-1:-1:-1;4916:16:40;;;4913:36;;;4945:1;4942;4935:12;4913:36;;4984:72;5048:7;5037:8;5026:9;5022:24;4984:72;:::i;:::-;4343:773;;;;-1:-1:-1;5075:8:40;-1:-1:-1;;;;4343:773:40:o;5306:127::-;5367:10;5362:3;5358:20;5355:1;5348:31;5398:4;5395:1;5388:15;5422:4;5419:1;5412:15;5438:125;5503:9;;;5524:10;;;5521:36;;;5537:18;;:::i;5568:408::-;5770:2;5752:21;;;5809:2;5789:18;;;5782:30;5848:34;5843:2;5828:18;;5821:62;-1:-1:-1;;;5914:2:40;5899:18;;5892:42;5966:3;5951:19;;5568:408::o;5981:::-;6183:2;6165:21;;;6222:2;6202:18;;;6195:30;6261:34;6256:2;6241:18;;6234:62;-1:-1:-1;;;6327:2:40;6312:18;;6305:42;6379:3;6364:19;;5981:408::o;6819:127::-;6880:10;6875:3;6871:20;6868:1;6861:31;6911:4;6908:1;6901:15;6935:4;6932:1;6925:15;6951:128;7018:9;;;7039:11;;;7036:37;;;7053:18;;:::i;7084:127::-;7145:10;7140:3;7136:20;7133:1;7126:31;7176:4;7173:1;7166:15;7200:4;7197:1;7190:15;7216:135;7255:3;7276:17;;;7273:43;;7296:18;;:::i;:::-;-1:-1:-1;7343:1:40;7332:13;;7216:135::o;8807:168::-;8880:9;;;8911;;8928:15;;;8922:22;;8908:37;8898:71;;8949:18;;:::i;8980:217::-;9020:1;9046;9036:132;;9090:10;9085:3;9081:20;9078:1;9071:31;9125:4;9122:1;9115:15;9153:4;9150:1;9143:15;9036:132;-1:-1:-1;9182:9:40;;8980:217::o;9202:311::-;9290:19;;;9272:3;-1:-1:-1;;;;;9321:31:40;;9318:51;;;9365:1;9362;9355:12;9318:51;9401:6;9398:1;9394:14;9453:8;9446:5;9439:4;9434:3;9430:14;9417:45;9482:18;;;;9502:4;9478:29;;9202:311;-1:-1:-1;;;9202:311:40:o;9518:519::-;9795:2;9784:9;9777:21;9758:4;9821:73;9890:2;9879:9;9875:18;9867:6;9859;9821:73;:::i;:::-;9942:9;9934:6;9930:22;9925:2;9914:9;9910:18;9903:50;9970:61;10024:6;10016;10008;9970:61;:::i;:::-;9962:69;9518:519;-1:-1:-1;;;;;;;9518:519:40:o;10295:184::-;10365:6;10418:2;10406:9;10397:7;10393:23;10389:32;10386:52;;;10434:1;10431;10424:12;10386:52;-1:-1:-1;10457:16:40;;10295:184;-1:-1:-1;10295:184:40:o;12135:250::-;12220:1;12230:113;12244:6;12241:1;12238:13;12230:113;;;12320:11;;;12314:18;12301:11;;;12294:39;12266:2;12259:10;12230:113;;;-1:-1:-1;;12377:1:40;12359:16;;12352:27;12135:250::o;12390:287::-;12519:3;12557:6;12551:13;12573:66;12632:6;12627:3;12620:4;12612:6;12608:17;12573:66;:::i;:::-;12655:16;;;;;12390:287;-1:-1:-1;;12390:287:40:o;13040:396::-;13189:2;13178:9;13171:21;13152:4;13221:6;13215:13;13264:6;13259:2;13248:9;13244:18;13237:34;13280:79;13352:6;13347:2;13336:9;13332:18;13327:2;13319:6;13315:15;13280:79;:::i;:::-;13420:2;13399:15;-1:-1:-1;;13395:29:40;13380:45;;;;13427:2;13376:54;;13040:396;-1:-1:-1;;13040:396:40:o","linkReferences":{},"immutableReferences":{"43952":[{"start":1512,"length":32},{"start":1585,"length":32},{"start":1744,"length":32},{"start":1808,"length":32},{"start":2079,"length":32}]}},"methodIdentifiers":{"balances(bytes32)":"8909aa3f","batchDeduct(bytes32[],uint256[])":"d4284d27","createIdentifier()":"e9af001f","getBalance(bytes32)":"8e739461","getIdentifierOwner(bytes32)":"30433e33","getProxyRewards(address)":"ffeb7561","getUserIdentifierAt(address,uint256)":"af3a312d","getUserIdentifierCount(address)":"83e9724a","getUserIdentifiers(address)":"9c65d667","identifierOwners(bytes32)":"d56cc9fc","initialize(address,uint256)":"cd6dc687","isProxy(address)":"29710388","owner()":"8da5cb5b","pricePerGB()":"1cf30841","proxiableUUID()":"52d1902d","proxyRewards(address)":"b7f12f26","setPricePerGB(uint256)":"e35ce0bb","setProxy(address,bool)":"51a39a58","topup(bytes32)":"2bc73c06","transferIdentifier(bytes32,address)":"6289ea64","upgradeTo(address)":"3659cfe6","upgradeToAndCall(address,bytes)":"4f1ef286","userIdentifiers(address,uint256)":"35fe94ee","withdrawRewards()":"c7b8981c"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoIdentifier\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotIdentifierOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32[]\",\"name\":\"identifiers\",\"type\":\"bytes32[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"bytesUsed\",\"type\":\"uint256[]\"}],\"name\":\"BatchDeduct\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"identifier\",\"type\":\"bytes32\"}],\"name\":\"IdentifierCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"identifier\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"IdentifierTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"pricePerGB\",\"type\":\"uint256\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newPrice\",\"type\":\"uint256\"}],\"name\":\"PriceUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"RewardsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"identifier\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TopUp\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"balances\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"identifiers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"bytesUsed\",\"type\":\"uint256[]\"}],\"name\":\"batchDeduct\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createIdentifier\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"identifier\",\"type\":\"bytes32\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"identifier\",\"type\":\"bytes32\"}],\"name\":\"getIdentifierOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"getProxyRewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getUserIdentifierAt\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"getUserIdentifierCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"getUserIdentifiers\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"identifierOwners\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pricePerGB\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isProxy\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pricePerGB\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"proxyRewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newPrice\",\"type\":\"uint256\"}],\"name\":\"setPricePerGB\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"authorized\",\"type\":\"bool\"}],\"name\":\"setProxy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"identifier\",\"type\":\"bytes32\"}],\"name\":\"topup\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"identifier\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferIdentifier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"userIdentifiers\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawRewards\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"},\"BeaconUpgraded(address)\":{\"details\":\"Emitted when the beacon is changed.\"},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"upgradeTo(address)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/Credits.sol\":\"Credits\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/\"]},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC1967Upgradeable.sol\":{\"keccak256\":\"0x47d6e06872b12e72c79d1b5eb55842f860b5fb1207b2317c2358d2766b950a7b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac55bf6f92fc7b90c6d79d346163a0a02bd5c648c7fede08b20e5da96d4ae2a0\",\"dweb:/ipfs/QmQoSrHhka35iKDK5iyNt8cuXXS5ANXVPjLhfsJjktB8V9\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol\":{\"keccak256\":\"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053\",\"dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol\":{\"keccak256\":\"0x584ebdf9c1118a7c773f98788e3f3ede01982bdf8932aa06f5acc7d54876e161\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9826c7edf276ff48b99ee217358393097c30448a71d345d287c2f6961bb1f159\",\"dweb:/ipfs/QmYXBTY9wDvffGU47yMRFJ1NFyKwpbj94VHzRzhsm6R7Gz\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol\":{\"keccak256\":\"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1\",\"dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f103ee2e4aecd37aac6ceefe670709cdd7613dee25fa2d4d9feaf7fc0aaa155e\",\"dweb:/ipfs/QmRiNZLoJk5k3HPMYGPGjZFd2ke1ZxjhJZkM45Ec9GH9hv\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"keccak256\":\"0xb607cb94c27e89750f5ae2ccebcb94e654e926f6125f4fd4c6262c89875118ad\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33e8f8d863c6943ea046fcf4972b4e815c04ab06bad195dba1d93f8ebeb8420d\",\"dweb:/ipfs/QmTQzxQTuuzPDk3eqVmYy7hv2RCXM1yt1NtubXpRbzYjaj\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://310136ad60820af4177a11a61d77a3686faf5fca4942b600e08fc940db38396b\",\"dweb:/ipfs/QmbCzMNSTL7Zi7M4UCSqBrkHtp4jjxUnGbkneCZKdR1qeq\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol\":{\"keccak256\":\"0x07ac95acad040f1fb1f6120dd0aa5f702db69446e95f82613721879d30de0908\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a9df9de7b5da1d1bd3d4b6c073d0174bc4211db60e794a321c8cb5d4eae34685\",\"dweb:/ipfs/QmWe49zj65jayrCe9jZpoWhYUZ1RiwSxyU2s7SBZnMztVy\"]},\"src/Credits.sol\":{\"keccak256\":\"0xbdef971339718360dc3c49ca5bc2e4d93124ebff373aea62a49074af82670b55\",\"license\":\"UNLICENSED\",\"urls\":[\"bzz-raw://d5e8f2d2bacc5d1f443a5c931c7011ec12b1fd3617abb325b7794cc5f1dd45c7\",\"dweb:/ipfs/QmbSbGqXvy5MnJJ7qoWCsWoKNH1WBEiMxuPtq6TG97hdK9\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.19+commit.7dd6d404"},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"type":"error","name":"ArrayLengthMismatch"},{"inputs":[],"type":"error","name":"InsufficientBalance"},{"inputs":[],"type":"error","name":"InvalidAddress"},{"inputs":[],"type":"error","name":"InvalidAmount"},{"inputs":[],"type":"error","name":"NoIdentifier"},{"inputs":[],"type":"error","name":"NotIdentifierOwner"},{"inputs":[],"type":"error","name":"TransferFailed"},{"inputs":[],"type":"error","name":"Unauthorized"},{"inputs":[],"type":"error","name":"ZeroAddress"},{"inputs":[{"internalType":"address","name":"previousAdmin","type":"address","indexed":false},{"internalType":"address","name":"newAdmin","type":"address","indexed":false}],"type":"event","name":"AdminChanged","anonymous":false},{"inputs":[{"internalType":"bytes32[]","name":"identifiers","type":"bytes32[]","indexed":false},{"internalType":"uint256[]","name":"bytesUsed","type":"uint256[]","indexed":false}],"type":"event","name":"BatchDeduct","anonymous":false},{"inputs":[{"internalType":"address","name":"beacon","type":"address","indexed":true}],"type":"event","name":"BeaconUpgraded","anonymous":false},{"inputs":[{"internalType":"address","name":"owner","type":"address","indexed":true},{"internalType":"bytes32","name":"identifier","type":"bytes32","indexed":true}],"type":"event","name":"IdentifierCreated","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32","indexed":true},{"internalType":"address","name":"from","type":"address","indexed":true},{"internalType":"address","name":"to","type":"address","indexed":true}],"type":"event","name":"IdentifierTransfer","anonymous":false},{"inputs":[{"internalType":"address","name":"owner","type":"address","indexed":false},{"internalType":"uint256","name":"pricePerGB","type":"uint256","indexed":false}],"type":"event","name":"Initialized","anonymous":false},{"inputs":[{"internalType":"uint8","name":"version","type":"uint8","indexed":false}],"type":"event","name":"Initialized","anonymous":false},{"inputs":[{"internalType":"uint256","name":"oldPrice","type":"uint256","indexed":false},{"internalType":"uint256","name":"newPrice","type":"uint256","indexed":false}],"type":"event","name":"PriceUpdate","anonymous":false},{"inputs":[{"internalType":"address","name":"proxy","type":"address","indexed":true},{"internalType":"uint256","name":"amount","type":"uint256","indexed":false}],"type":"event","name":"RewardsWithdrawn","anonymous":false},{"inputs":[{"internalType":"address","name":"from","type":"address","indexed":true},{"internalType":"bytes32","name":"identifier","type":"bytes32","indexed":true},{"internalType":"uint256","name":"amount","type":"uint256","indexed":false}],"type":"event","name":"TopUp","anonymous":false},{"inputs":[{"internalType":"address","name":"implementation","type":"address","indexed":true}],"type":"event","name":"Upgraded","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function","name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"bytes32[]","name":"identifiers","type":"bytes32[]"},{"internalType":"uint256[]","name":"bytesUsed","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function","name":"batchDeduct"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"createIdentifier","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getIdentifierOwner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"proxy","type":"address"}],"stateMutability":"view","type":"function","name":"getProxyRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getUserIdentifierAt","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"stateMutability":"view","type":"function","name":"getUserIdentifierCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"stateMutability":"view","type":"function","name":"getUserIdentifiers","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}]},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function","name":"identifierOwners","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_pricePerGB","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"initialize"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"isProxy","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"pricePerGB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"proxyRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"setPricePerGB"},{"inputs":[{"internalType":"address","name":"proxy","type":"address"},{"internalType":"bool","name":"authorized","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setProxy"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"}],"stateMutability":"payable","type":"function","name":"topup"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"address","name":"to","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferIdentifier"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"upgradeTo"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"payable","type":"function","name":"upgradeToAndCall"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function","name":"userIdentifiers","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"withdrawRewards"}],"devdoc":{"kind":"dev","methods":{"constructor":{"custom:oz-upgrades-unsafe-allow":"constructor"},"proxiableUUID()":{"details":"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier."},"upgradeTo(address)":{"custom:oz-upgrades-unsafe-allow-reachable":"delegatecall","details":"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event."},"upgradeToAndCall(address,bytes)":{"custom:oz-upgrades-unsafe-allow-reachable":"delegatecall","details":"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event."}},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":["@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","ds-test/=lib/forge-std/lib/ds-test/src/","erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/","openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/Credits.sol":"Credits"},"evmVersion":"paris","libraries":{}},"sources":{"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC1967Upgradeable.sol":{"keccak256":"0x47d6e06872b12e72c79d1b5eb55842f860b5fb1207b2317c2358d2766b950a7b","urls":["bzz-raw://ac55bf6f92fc7b90c6d79d346163a0a02bd5c648c7fede08b20e5da96d4ae2a0","dweb:/ipfs/QmQoSrHhka35iKDK5iyNt8cuXXS5ANXVPjLhfsJjktB8V9"],"license":"MIT"},"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol":{"keccak256":"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f","urls":["bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053","dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79"],"license":"MIT"},"lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol":{"keccak256":"0x584ebdf9c1118a7c773f98788e3f3ede01982bdf8932aa06f5acc7d54876e161","urls":["bzz-raw://9826c7edf276ff48b99ee217358393097c30448a71d345d287c2f6961bb1f159","dweb:/ipfs/QmYXBTY9wDvffGU47yMRFJ1NFyKwpbj94VHzRzhsm6R7Gz"],"license":"MIT"},"lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol":{"keccak256":"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908","urls":["bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1","dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ"],"license":"MIT"},"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol":{"keccak256":"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794","urls":["bzz-raw://f103ee2e4aecd37aac6ceefe670709cdd7613dee25fa2d4d9feaf7fc0aaa155e","dweb:/ipfs/QmRiNZLoJk5k3HPMYGPGjZFd2ke1ZxjhJZkM45Ec9GH9hv"],"license":"MIT"},"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol":{"keccak256":"0xb607cb94c27e89750f5ae2ccebcb94e654e926f6125f4fd4c6262c89875118ad","urls":["bzz-raw://33e8f8d863c6943ea046fcf4972b4e815c04ab06bad195dba1d93f8ebeb8420d","dweb:/ipfs/QmTQzxQTuuzPDk3eqVmYy7hv2RCXM1yt1NtubXpRbzYjaj"],"license":"MIT"},"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol":{"keccak256":"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422","urls":["bzz-raw://310136ad60820af4177a11a61d77a3686faf5fca4942b600e08fc940db38396b","dweb:/ipfs/QmbCzMNSTL7Zi7M4UCSqBrkHtp4jjxUnGbkneCZKdR1qeq"],"license":"MIT"},"lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol":{"keccak256":"0x07ac95acad040f1fb1f6120dd0aa5f702db69446e95f82613721879d30de0908","urls":["bzz-raw://a9df9de7b5da1d1bd3d4b6c073d0174bc4211db60e794a321c8cb5d4eae34685","dweb:/ipfs/QmWe49zj65jayrCe9jZpoWhYUZ1RiwSxyU2s7SBZnMztVy"],"license":"MIT"},"src/Credits.sol":{"keccak256":"0xbdef971339718360dc3c49ca5bc2e4d93124ebff373aea62a49074af82670b55","urls":["bzz-raw://d5e8f2d2bacc5d1f443a5c931c7011ec12b1fd3617abb325b7794cc5f1dd45c7","dweb:/ipfs/QmbSbGqXvy5MnJJ7qoWCsWoKNH1WBEiMxuPtq6TG97hdK9"],"license":"UNLICENSED"}},"version":1},"id":37} \ No newline at end of file diff --git a/packages/plugin-eigenda/src/actions/getStatus.ts b/packages/plugin-eigenda/src/actions/getStatus.ts new file mode 100644 index 00000000000..ed197d4137d --- /dev/null +++ b/packages/plugin-eigenda/src/actions/getStatus.ts @@ -0,0 +1,198 @@ +import { + ActionExample, + Content, + HandlerCallback, + IAgentRuntime, + Memory, + ModelClass, + State, + type Action, + elizaLogger, + composeContext, + generateObjectDeprecated, +} from "@elizaos/core"; +import { validateEigenDAConfig } from "../environment"; +import { getClient } from "../utils"; + +export interface StatusContent extends Content { + jobId: string; +} + +export function isStatusContent(content: StatusContent): content is StatusContent { + return typeof content.jobId === "string"; +} + +const statusTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. + +Example response: +\`\`\`json +{ + "jobId": "abc123def456" +} +\`\`\` + +{{recentMessages}} + +Given the recent messages, extract the following information about the requested EigenDA status check: +- Job ID to check status for + +Respond with a JSON markdown block containing only the extracted values.`; + +export default { + name: "GET_STATUS", + similes: [ + "CHECK_STATUS", + "GET_JOB_STATUS", + "CHECK_JOB_STATUS", + "GET_UPLOAD_STATUS", + "CHECK_UPLOAD_STATUS", + "GET_EIGENDA_STATUS", + "CHECK_EIGENDA_STATUS", + ], + validate: async (runtime: IAgentRuntime, _message: Memory) => { + await validateEigenDAConfig(runtime); + return true; + }, + description: "Check the status of an EigenDA upload job. Gives out the status, request ID and blob info.", + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state: State, + _options: { [key: string]: unknown }, + callback?: HandlerCallback + ): Promise => { + elizaLogger.log("Starting GET_STATUS handler..."); + + // Initialize or update state + if (!state) { + state = (await runtime.composeState(message)) as State; + } else { + state = await runtime.updateRecentMessageState(state); + } + + // Compose status context + const statusContext = composeContext({ + state, + template: statusTemplate, + }); + + // Generate status content + const content = await generateObjectDeprecated({ + runtime, + context: statusContext, + modelClass: ModelClass.SMALL, + }); + + // Validate status content + if (!isStatusContent(content)) { + console.error("Invalid content for GET_STATUS action."); + if (callback) { + callback({ + text: "Unable to process status request. Invalid content provided.", + content: { error: "Invalid status content" }, + }); + } + return false; + } + + if (content.jobId != null) { + try { + const client = getClient(); + const status = await client.getStatus(content.jobId); + const requestId = status.request_id; + const blobInfo = status.blob_info; + elizaLogger.log(`Request ID: ${requestId}, Blob Info: ${blobInfo}`); + elizaLogger.success( + `Successfully retrieved status for job ${content.jobId}: ${JSON.stringify(status)}` + ); + if (callback) { + callback({ + text: `Current status for job ${content.jobId}: ${status.status}${status.error ? `. Error: ${status.error}` : ''} \n You can also track it with Request ID: ${status.request_id}`, + content: status, + }); + } + + return true; + } catch (error) { + elizaLogger.error("Error checking status:", error); + if (callback) { + callback({ + text: `Error checking status: ${error.message}`, + content: { error: error.message }, + }); + } + return false; + } + } else { + elizaLogger.log("No job ID provided to check status"); + return false; + } + }, + + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "Check the status of job abc123def456", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll check the status of that job for you.", + action: "GET_STATUS", + }, + }, + { + user: "{{agent}}", + content: { + text: "The status of job abc123def456 is COMPLETED, Request ID: abc123def456", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "What's the status of my upload with job ID xyz789?", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll check the status of your upload.", + action: "GET_STATUS", + }, + }, + { + user: "{{agent}}", + content: { + text: "The status of job xyz789 is PROCESSING, Request ID: abc123def456", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "What's the Request ID for my upload with job ID xyz789?", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll check the request ID for your upload.", + action: "GET_STATUS", + }, + }, + { + user: "{{agent}}", + content: { + text: "The request ID for job xyz789 is abc123def456", + }, + }, + ] + ] as ActionExample[][], +} as Action; + diff --git a/packages/plugin-eigenda/src/actions/retrieveData.ts b/packages/plugin-eigenda/src/actions/retrieveData.ts new file mode 100644 index 00000000000..3f62ea45a77 --- /dev/null +++ b/packages/plugin-eigenda/src/actions/retrieveData.ts @@ -0,0 +1,245 @@ +import { + ActionExample, + Content, + HandlerCallback, + IAgentRuntime, + Memory, + ModelClass, + State, + type Action, + elizaLogger, + composeContext, + generateObjectDeprecated, +} from "@elizaos/core"; +import { validateEigenDAConfig } from "../environment"; +import { getClient } from "../utils"; + +export interface RetrieveContent extends Content { + jobId?: string; + requestId?: string; + batchHeaderHash?: string; + blobIndex?: number; +} + +export function isRetrieveContent(content: RetrieveContent): content is RetrieveContent { + // At least one of these must be provided + return !!(content.jobId || (content.requestId) || (content.batchHeaderHash && typeof content.blobIndex === 'number')); +} + +const retrieveTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. + +Example response: +\`\`\`json +{ + "jobId": "abc123def456", + "requestId": null, + "batchHeaderHash": null, + "blobIndex": null +} +\`\`\` + +{{recentMessages}} + +Given the recent messages, extract the following information about the requested EigenDA retrieval: +- Job ID (if provided) +- Request ID (if provided) +- Batch Header Hash (if provided) +- Blob Index (if provided with Batch Header Hash) + +Respond with a JSON markdown block containing only the extracted values.`; + +export default { + name: "RETRIEVE_DATA", + similes: [ + "RETRIEVE_FROM_EIGENDA", + "RETRIEVE_CONTENT", + "RETRIEVE_FILE", + "GET_DATA", + "GET_CONTENT", + "GET_FILE", + "FETCH_DATA", + "FETCH_CONTENT", + "FETCH_FILE", + "DOWNLOAD_DATA", + "DOWNLOAD_CONTENT", + "DOWNLOAD_FILE", + ], + validate: async (runtime: IAgentRuntime, _message: Memory) => { + await validateEigenDAConfig(runtime); + return true; + }, + description: "Retrieve content from EigenDA", + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state: State, + _options: { [key: string]: unknown }, + callback?: HandlerCallback + ): Promise => { + elizaLogger.log("Starting RETRIEVE_DATA handler..."); + + // Initialize or update state + if (!state) { + state = (await runtime.composeState(message)) as State; + } else { + state = await runtime.updateRecentMessageState(state); + } + + // Compose retrieve context + const retrieveContext = composeContext({ + state, + template: retrieveTemplate, + }); + + // Generate retrieve content + const content = await generateObjectDeprecated({ + runtime, + context: retrieveContext, + modelClass: ModelClass.SMALL, + }); + + // Validate retrieve content + if (!isRetrieveContent(content)) { + console.error("Invalid content for RETRIEVE_DATA action."); + if (callback) { + callback({ + text: "Unable to process retrieval request. Invalid content provided.", + content: { error: "Invalid retrieval content" }, + }); + } + return false; + } + + try { + const client = getClient(); + + // Prepare retrieval options based on provided parameters + const retrieveOptions: any = {}; + if (content.jobId) { + retrieveOptions.jobId = content.jobId; + } else if (content.requestId) { + retrieveOptions.requestId = content.requestId; + } else if (content.batchHeaderHash && content.blobIndex !== undefined) { + retrieveOptions.batchHeaderHash = content.batchHeaderHash; + retrieveOptions.blobIndex = content.blobIndex; + } else { + throw new Error("Must provide either jobId, requestId, or both batchHeaderHash and blobIndex"); + } + + // Retrieve the content + const retrievedContent = await client.retrieve(retrieveOptions); + + // Process the response similar to Python implementation + let processedContent; + let contentType = 'unknown'; + let size = 0; + + if (retrievedContent instanceof Uint8Array) { + size = retrievedContent.length; + try { + // First try to parse as JSON + const decodedString = new TextDecoder().decode(retrievedContent); + try { + processedContent = JSON.parse(decodedString); + contentType = 'json'; + } catch { + // Check if it's an image + if (retrievedContent.length > 4 && + (retrievedContent[0] === 0xFF && retrievedContent[1] === 0xD8 || // JPEG + retrievedContent[0] === 0x89 && retrievedContent[1] === 0x50)) // PNG + { + contentType = 'image'; + processedContent = ``; + } else { + // If not JSON or image, check if it's readable text + const isProbablyText = /^[\x20-\x7E\n\r\t]*$/.test(decodedString); + contentType = isProbablyText ? 'text' : 'binary'; + processedContent = isProbablyText ? decodedString : + ``; + } + } + } catch { + contentType = 'binary'; + processedContent = ``; + } + } else { + // Handle case where response is already parsed (e.g., JSON) + processedContent = retrievedContent; + contentType = 'json'; + size = JSON.stringify(retrievedContent).length; + } + + elizaLogger.success("Successfully retrieved content"); + if (callback) { + callback({ + text: `Retrieved ${contentType} content: ${ + typeof processedContent === 'object' + ? JSON.stringify(processedContent, null, 2) + : processedContent + }`, + content: { + data: retrievedContent, + contentType, + size + } + }); + } + + return true; + } catch (error) { + elizaLogger.error("Error retrieving content:", error); + if (callback) { + callback({ + text: `Error retrieving content: ${error.message}`, + content: { error: error.message }, + }); + } + return false; + } + }, + + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "Retrieve data for job abc123def456", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll retrieve that content from EigenDA for you.", + action: "RETRIEVE_DATA", + }, + }, + { + user: "{{agent}}", + content: { + text: "Retrieved content: Hello, EigenDA! This is a test message.", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Get the data with request ID xyz789", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll fetch that content for you.", + action: "RETRIEVE_DATA", + }, + }, + { + user: "{{agent}}", + content: { + text: 'Retrieved content: {"name": "Test Object", "values": [1, 2, 3, 4, 5]}', + }, + }, + ], + ] as ActionExample[][], +} as Action; diff --git a/packages/plugin-eigenda/src/actions/uploadData.ts b/packages/plugin-eigenda/src/actions/uploadData.ts new file mode 100644 index 00000000000..8cc961d8171 --- /dev/null +++ b/packages/plugin-eigenda/src/actions/uploadData.ts @@ -0,0 +1,221 @@ +import { + ActionExample, + Content, + HandlerCallback, + IAgentRuntime, + Memory, + ModelClass, + State, + type Action, + elizaLogger, + composeContext, + generateObjectDeprecated, +} from "@elizaos/core"; +import { validateEigenDAConfig } from "../environment"; +import { getClient } from "../utils"; + +export interface UploadContent extends Content { + content: string; + identifier?: string; +} + +export function isUploadContent(content: UploadContent): content is UploadContent { + return typeof content.content === "string"; +} + +const uploadTemplate = `Respond with a JSON markdown block containing only the extracted values. Use null for any values that cannot be determined. + +Example response: +\`\`\`json +{ + "content": "Hello, EigenDA! This is a test message.", + "identifier": "0x1234567890abcdef" +} +\`\`\` + +{{recentMessages}} + +Given the recent messages, extract the following information about the requested EigenDA upload: +- Content to upload +- (Optional) Identifier to use for upload +Respond with a JSON markdown block containing only the extracted values.`; + +export default { + name: "UPLOAD_DATA", + similes: [ + "UPLOAD_TO_EIGENDA", + "UPLOAD_CONTENT", + "UPLOAD_FILE", + "STORE_DATA", + "STORE_CONTENT", + "STORE_FILE", + "SAVE_DATA", + "SAVE_CONTENT", + "SAVE_FILE", + ], + validate: async (runtime: IAgentRuntime, _message: Memory) => { + await validateEigenDAConfig(runtime); + return true; + }, + description: "Upload content to EigenDA", + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state: State, + _options: { [key: string]: unknown }, + callback?: HandlerCallback + ): Promise => { + elizaLogger.log("Starting UPLOAD_DATA handler..."); + + // Initialize or update state + if (!state) { + state = (await runtime.composeState(message)) as State; + } else { + state = await runtime.updateRecentMessageState(state); + } + + // Compose upload context + const uploadContext = composeContext({ + state, + template: uploadTemplate, + }); + + // Generate upload content + const content = await generateObjectDeprecated({ + runtime, + context: uploadContext, + modelClass: ModelClass.SMALL, + }); + + // Validate upload content + if (!isUploadContent(content)) { + console.error("Invalid content for UPLOAD_DATA action."); + if (callback) { + callback({ + text: "Unable to process upload request. Invalid content provided.", + content: { error: "Invalid upload content" }, + }); + } + return false; + } + + if (content.content != null) { + try { + const client = getClient(); + + // Get or create identifier if not provided + let identifier: Uint8Array; + if (content.identifier) { + // Convert hex string to bytes32 format + const cleanHex = content.identifier.replace('0x', '').padStart(64, '0'); + identifier = new Uint8Array(Buffer.from(cleanHex, 'hex')); + } else { + // Check for environment identifier + const envConfig = await validateEigenDAConfig(runtime); + if (envConfig.IDENTIFIER) { + const cleanHex = envConfig.IDENTIFIER.replace('0x', '').padStart(64, '0'); + identifier = new Uint8Array(Buffer.from(cleanHex, 'hex')); + } else { + // Fall back to existing or new identifier + const identifiers = await client.getIdentifiers(); + identifier = identifiers.length > 0 + ? identifiers[0] + : await client.createIdentifier(); + } + } + + elizaLogger.log("Using identifier (hex):", Buffer.from(identifier).toString('hex')); + + // Check balance and top up if needed + const balance = await client.getBalance(identifier); + elizaLogger.log(`Current balance: ${balance} ETH`); + + // Top up if balance is too low (0.001 ETH) + if (balance < 0.001) { + elizaLogger.log("Balance low, topping up with 0.001 ETH..."); + const topupResult = await client.topupCredits(identifier, 0.001); + elizaLogger.log("Top-up transaction:", topupResult); + + // Wait a bit for the transaction to be processed + await new Promise(resolve => setTimeout(resolve, 5000)); + + // Check new balance + const newBalance = await client.getBalance(identifier); + elizaLogger.log(`New balance after top-up: ${newBalance} ETH`); + } + + // Upload the content + const uploadResult = await client.upload(content.content, identifier); + + elizaLogger.success( + `Successfully uploaded content. Job ID: ${uploadResult.job_id}` + ); + if (callback) { + callback({ + text: `Content uploaded successfully! Job ID: ${uploadResult.job_id}. You can check the status of your upload using this job ID.`, + content: uploadResult, + }); + } + + return true; + } catch (error) { + elizaLogger.error("Error uploading content:", error); + if (callback) { + callback({ + text: `Error uploading content: ${error.message}`, + content: { error: error.message }, + }); + } + return false; + } + } else { + elizaLogger.log("No content provided to upload"); + return false; + } + }, + + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "Upload 'Hello, EigenDA!' to the network", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll upload that content to EigenDA for you.", + action: "UPLOAD_DATA", + }, + }, + { + user: "{{agent}}", + content: { + text: "Content uploaded successfully! Job ID: abc123def456. You can check the status of your upload using this job ID.", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Store this JSON data: {'name': 'Test', 'value': 123}", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll store that JSON data on EigenDA.", + action: "UPLOAD_DATA", + }, + }, + { + user: "{{agent}}", + content: { + text: "JSON data uploaded successfully! Job ID: xyz789. You can check the status of your upload using this job ID.", + }, + }, + ], + ] as ActionExample[][], +} as Action; diff --git a/packages/plugin-eigenda/src/environment.ts b/packages/plugin-eigenda/src/environment.ts new file mode 100644 index 00000000000..62a0ad26625 --- /dev/null +++ b/packages/plugin-eigenda/src/environment.ts @@ -0,0 +1,46 @@ +import { IAgentRuntime } from "@elizaos/core"; +import { z } from "zod"; + +export const eigenDAEnvSchema = z.object({ + API_URL: z.string().optional(), + BASE_RPC_URL: z.string().optional(), + EIGENDA_PRIVATE_KEY: z.string().min(1, "Private key is required"), + CREDITS_CONTRACT_ADDRESS: z.string().optional(), + IDENTIFIER: z.string().optional(), +}); + +export type EigenDAConfig = z.infer; + +export async function validateEigenDAConfig( + runtime: IAgentRuntime +): Promise { + try { + const config = { + API_URL: runtime.getSetting("API_URL") || process.env.API_URL || DEFAULT_API_URL, + BASE_RPC_URL: runtime.getSetting("BASE_RPC_URL") || process.env.BASE_RPC_URL || DEFAULT_RPC_URL, + EIGENDA_PRIVATE_KEY: runtime.getSetting("EIGENDA_PRIVATE_KEY") || process.env.EIGENDA_PRIVATE_KEY, + CREDITS_CONTRACT_ADDRESS: runtime.getSetting("CREDITS_CONTRACT_ADDRESS") || process.env.CREDITS_CONTRACT_ADDRESS || DEFAULT_CREDITS_CONTRACT_ADDRESS, + IDENTIFIER: runtime.getSetting("EIGENDA_IDENTIFIER") || process.env.EIGENDA_IDENTIFIER, + }; + + return eigenDAEnvSchema.parse(config); + } catch (error) { + if (error instanceof z.ZodError) { + const errorMessages = error.errors + .map((err) => `${err.path.join(".")}: ${err.message}`) + .join("\n"); + throw new Error( + `EigenDA configuration validation failed:\n${errorMessages}` + ); + } + throw error; + } +} + +// Default configuration values +export const DEFAULT_API_URL = "http://test-agent-proxy-api.eigenda.xyz"; +export const MAX_STATUS_CHECKS = 60; +export const STATUS_CHECK_INTERVAL = 10; +export const INITIAL_RETRIEVAL_DELAY = 300; +export const DEFAULT_CREDITS_CONTRACT_ADDRESS = "0x0CC001F1bDe9cd129092d4d24D935DB985Ce42A9"; +export const DEFAULT_RPC_URL = "https://mainnet.base.org"; \ No newline at end of file diff --git a/packages/plugin-eigenda/src/index.ts b/packages/plugin-eigenda/src/index.ts new file mode 100644 index 00000000000..a093ea8b162 --- /dev/null +++ b/packages/plugin-eigenda/src/index.ts @@ -0,0 +1,26 @@ +import type { Plugin } from "@elizaos/core"; + +// Export actions +export * from "./actions/uploadData"; +export * from "./actions/retrieveData"; +export * from "./actions/getStatus"; + +// Export utilities and types +export * from "./utils"; +export * from "./environment"; + +// Import actions +import uploadData from "./actions/uploadData"; +import retrieveData from "./actions/retrieveData"; +import getStatus from "./actions/getStatus"; + +export const eigendaPlugin: Plugin = { + name: "eigenda", + description: "EigenDA is a data availability plugin for storing and retrieving data", + providers: [], + evaluators: [], + services: [], + actions: [uploadData, retrieveData, getStatus], +}; + +export default eigendaPlugin; \ No newline at end of file diff --git a/packages/plugin-eigenda/src/utils.ts b/packages/plugin-eigenda/src/utils.ts new file mode 100644 index 00000000000..0c2f0eb74ee --- /dev/null +++ b/packages/plugin-eigenda/src/utils.ts @@ -0,0 +1,304 @@ +import { ethers } from 'ethers'; +import { config } from 'dotenv'; +import axios from 'axios'; +import { randomBytes } from 'crypto'; +import { elizaLogger } from '@elizaos/core'; +import { DEFAULT_API_URL, DEFAULT_CREDITS_CONTRACT_ADDRESS, DEFAULT_RPC_URL } from "./environment"; + +// Load environment variables +config(); + +// Default configuration +const MAX_STATUS_CHECKS = 60; // Maximum number of status checks (10 minutes with 10-second interval) +const STATUS_CHECK_INTERVAL = 10; // Seconds between status checks +const INITIAL_RETRIEVAL_DELAY = 300; // 5 minutes initial delay before first retrieval attempt + +interface EigenDAClientConfig { + apiUrl?: string; + rpcUrl?: string; + privateKey?: string; + creditsContractAddress?: string; +} + +interface UploadResponse { + job_id: string; + request_id: string; +} + +interface StatusResponse { + status: string; + request_id?: string; + blob_info?: any; + error?: string; +} + +export class EigenDAClient { + private apiUrl: string; + private provider: ethers.JsonRpcProvider; + private wallet: ethers.Wallet; + private creditsContract: ethers.Contract; + private creditsAbi: any; + + constructor(config?: EigenDAClientConfig) { + this.apiUrl = (config?.apiUrl || process.env.API_URL || DEFAULT_API_URL).replace(/\/$/, ''); + + // Setup provider + const rpcUrl = config?.rpcUrl || process.env.BASE_RPC_URL || DEFAULT_RPC_URL; + this.provider = new ethers.JsonRpcProvider(rpcUrl); + + // Setup wallet + const privateKey = config?.privateKey || process.env.EIGENDA_PRIVATE_KEY; + if (!privateKey) { + throw new Error("Private key not provided and EIGENDA_PRIVATE_KEY not set in environment"); + } + const normalizedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`; + this.wallet = new ethers.Wallet(normalizedPrivateKey, this.provider); + + // Setup contract + const creditsContractAddress = config?.creditsContractAddress || process.env.CREDITS_CONTRACT_ADDRESS || DEFAULT_CREDITS_CONTRACT_ADDRESS; + + // Load contract ABI + try { + this.creditsAbi = require('./abi/Credits.json').abi; + this.creditsContract = new ethers.Contract(creditsContractAddress, this.creditsAbi, this.wallet); + } catch (error) { + throw new Error("Credits ABI file not found. Please ensure abi/Credits.json exists"); + } + } + + private async signRequest(requestData: any): Promise { + // Convert request data to a consistent format + const dataToSign = { + content: requestData.content, + salt: requestData.salt + }; + + // Convert to JSON string with sorted keys (matching Python's json.dumps with sort_keys=True) + const message = JSON.stringify(dataToSign, Object.keys(dataToSign).sort()); + elizaLogger.debug('Message to sign:', message); + + // Sign the message directly (not the hash) + const signature = await this.wallet.signMessage(message); + return signature; + } + + async createIdentifier(): Promise { + try { + const tx = await this.creditsContract.createIdentifier(); + const receipt = await tx.wait(); + + const event = receipt.logs + .map(log => this.creditsContract.interface.parseLog(log)) + .find(event => event?.name === 'IdentifierCreated'); + + if (event) { + // Convert the identifier to proper bytes32 format + const identifier = event.args.identifier; + // Remove '0x' prefix if present and ensure 32 bytes + const hexString = identifier.slice(0, 2) === '0x' ? identifier.slice(2) : identifier; + return ethers.getBytes('0x' + hexString.padStart(64, '0')); + } + throw new Error("No identifier in event logs"); + } catch (error) { + throw new Error(`Failed to create identifier: ${error.message}`); + } + } + + async getIdentifiers(): Promise { + try { + const count = await this.creditsContract.getUserIdentifierCount(this.wallet.address); + const identifiers = await Promise.all( + Array.from({ length: Number(count) }, (_, i) => + this.creditsContract.getUserIdentifierAt(this.wallet.address, i) + ) + ); + // Convert each identifier to proper bytes32 format + return identifiers.map(id => { + const hexString = id.slice(0, 2) === '0x' ? id.slice(2) : id; + return ethers.getBytes('0x' + hexString.padStart(64, '0')); + }); + } catch (error) { + throw new Error(`Failed to get identifiers: ${error.message}`); + } + } + + async getBalance(identifier: Uint8Array): Promise { + try { + // Convert identifier to proper bytes32 format + const hexString = Buffer.from(identifier).toString('hex'); + const formattedIdentifier = ethers.hexlify(ethers.zeroPadValue('0x' + hexString, 32)); + const balance = await this.creditsContract.getBalance(formattedIdentifier); + return Number(ethers.formatEther(balance)); + } catch (error) { + throw new Error(`Failed to get balance: ${error.message}`); + } + } + + async topupCredits(identifier: Uint8Array, amountEth: number): Promise<{ transactionHash: string; status: string }> { + try { + // Convert identifier to proper bytes32 format + const hexString = Buffer.from(identifier).toString('hex'); + const formattedIdentifier = ethers.hexlify(ethers.zeroPadValue('0x' + hexString, 32)); + const tx = await this.creditsContract.topup(formattedIdentifier, { + value: ethers.parseEther(amountEth.toString()) + }); + const receipt = await tx.wait(); + + return { + transactionHash: receipt.hash, + status: receipt.status === 1 ? 'success' : 'failed' + }; + } catch (error) { + throw new Error(`Failed to top up credits: ${error.message}`); + } + } + + async upload(content: string, identifier: Uint8Array): Promise { + try { + // Treat content as a string for proper signing and serialization + const salt = randomBytes(32).toString('hex'); + + // Convert identifier to proper hex format for the API + const identifierHex = Buffer.from(identifier).toString('hex').padStart(64, '0'); + + // Create the data that will be signed (matching Python example) + const dataToSign = { + content: content, + salt: salt + }; + + // Sign the request + const signature = await this.signRequest(dataToSign); + + // Create the full request data + const requestData = { + content: content, + account_id: this.wallet.address, + identifier: identifierHex, + salt: salt, + signature: signature + }; + + // Make the request + try { + const response = await axios.post(`${this.apiUrl}/upload`, requestData); + return response.data; + } catch (axiosError: any) { + elizaLogger.error('Upload request failed:'); + elizaLogger.error(`Status: ${axiosError.response?.status}`); + elizaLogger.error(`Response data:`, axiosError.response?.data); + throw new Error(`Upload request failed: ${axiosError.response?.data?.error || axiosError.message}`); + } + } catch (error: any) { + elizaLogger.error('Error in upload method:', error); + throw error; + } + } + + async getStatus(jobId: string): Promise { + try { + const response = await axios.get(`${this.apiUrl}/status/${jobId}`); + return response.data; + } catch (error) { + throw new Error(`Failed to get status: ${error.message}`); + } + } + + async waitForStatus( + jobId: string, + targetStatus: string = "CONFIRMED" || "FINALIZED", + maxChecks: number = MAX_STATUS_CHECKS, + checkInterval: number = STATUS_CHECK_INTERVAL, + initialDelay: number = INITIAL_RETRIEVAL_DELAY + ): Promise { + console.log(`Waiting ${initialDelay} seconds before first status check...`); + await new Promise(resolve => setTimeout(resolve, initialDelay * 1000)); + + let checks = 0; + while (checks < maxChecks) { + const statusResponse = await this.getStatus(jobId); + const currentStatus = statusResponse.status; + console.log(`Current status: ${currentStatus}`); + + if (currentStatus === targetStatus) { + return statusResponse; + } else if (currentStatus === "FAILED") { + throw new Error(`Job failed: ${statusResponse.error || 'Unknown error'}`); + } + + checks++; + if (checks < maxChecks) { + console.log(`Waiting ${checkInterval} seconds before next check... (${checks}/${maxChecks})`); + await new Promise(resolve => setTimeout(resolve, checkInterval * 1000)); + } + } + + throw new Error(`Timeout waiting for status ${targetStatus} after ${maxChecks} checks`); + } + + async retrieve( + options: { + jobId?: string; + requestId?: string; + batchHeaderHash?: string; + blobIndex?: number; + waitForCompletion?: boolean; + } + ): Promise { + try { + const { jobId, requestId, batchHeaderHash, blobIndex, waitForCompletion = false } = options; + + // If using jobId and waitForCompletion is false, wait for the job to complete + let finalRequestId = requestId; + if (jobId && waitForCompletion) { + const status = await this.waitForStatus(jobId); + finalRequestId = status.request_id; + if (!finalRequestId) { + throw new Error("No request_id in completed status"); + } + } + + // Prepare request data + const requestData: any = {}; + if (finalRequestId) { + requestData.request_id = finalRequestId; + } else if (jobId) { + requestData.job_id = jobId; + } else if (batchHeaderHash && blobIndex !== undefined) { + requestData.batch_header_hash = batchHeaderHash; + requestData.blob_index = blobIndex; + } else { + throw new Error( + "Must provide either jobId, requestId, or both batchHeaderHash and blobIndex" + ); + } + + // Make retrieval request + const response = await axios.post(`${this.apiUrl}/retrieve`, requestData, { + responseType: 'arraybuffer' + }); + + // Try to parse as JSON first + try { + const textContent = new TextDecoder().decode(response.data); + return JSON.parse(textContent); + } catch { + // If not JSON, return as Uint8Array + return new Uint8Array(response.data); + } + } catch (error) { + throw new Error(`Failed to retrieve content: ${error.message}`); + } + } +} + +export function getClient(config?: EigenDAClientConfig): EigenDAClient { + // Ensure we're using the same config priority as in environment.ts + const clientConfig: EigenDAClientConfig = { + apiUrl: config?.apiUrl || process.env.API_URL || DEFAULT_API_URL, + rpcUrl: config?.rpcUrl || process.env.BASE_RPC_URL || DEFAULT_RPC_URL, + privateKey: config?.privateKey || process.env.EIGENDA_PRIVATE_KEY, + creditsContractAddress: config?.creditsContractAddress || process.env.CREDITS_CONTRACT_ADDRESS || DEFAULT_CREDITS_CONTRACT_ADDRESS, + }; + return new EigenDAClient(clientConfig); +} \ No newline at end of file diff --git a/packages/plugin-eigenda/tsconfig.json b/packages/plugin-eigenda/tsconfig.json new file mode 100644 index 00000000000..18c600eec05 --- /dev/null +++ b/packages/plugin-eigenda/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../core/tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "types": [ + "node" + ] + }, + "include": [ + "src/**/*.ts", + ] +} \ No newline at end of file diff --git a/packages/plugin-eigenda/tsup.config.ts b/packages/plugin-eigenda/tsup.config.ts new file mode 100644 index 00000000000..1a96f24afa1 --- /dev/null +++ b/packages/plugin-eigenda/tsup.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + sourcemap: true, + clean: true, + format: ["esm"], // Ensure you're targeting CommonJS + external: [ + "dotenv", // Externalize dotenv to prevent bundling + "fs", // Externalize fs to use Node.js built-in module + "path", // Externalize other built-ins if necessary + "@reflink/reflink", + "@node-llama-cpp", + "https", + "http", + "agentkeepalive", + "safe-buffer", + // Add other modules you want to externalize + ], +}); diff --git a/packages/plugin-opacity/package.json b/packages/plugin-opacity/package.json index c15b91872ea..6d9e1e9ccfb 100644 --- a/packages/plugin-opacity/package.json +++ b/packages/plugin-opacity/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@elizaos/core": "workspace:*", + "@elizaos/plugin-eigenda": "workspace:*", "dotenv": "^16.4.5" }, "devDependencies": { diff --git a/packages/plugin-opacity/src/index.ts b/packages/plugin-opacity/src/index.ts index ab1dccdb0cc..dd3786ff145 100644 --- a/packages/plugin-opacity/src/index.ts +++ b/packages/plugin-opacity/src/index.ts @@ -8,19 +8,59 @@ import { elizaLogger, } from "@elizaos/core"; import { verifyProof } from "./utils/api"; +import { EigenDAClient } from "@elizaos/plugin-eigenda"; + interface OpacityOptions { modelProvider?: ModelProviderName; token?: string; teamId?: string; teamName?: string; opacityProverUrl: string; + // EigenDA options + eigenDAPrivateKey?: string; + eigenDAApiUrl?: string; + eigenDARpcUrl?: string; + eigenDACreditsContractAddress?: string; } export class OpacityAdapter implements IVerifiableInferenceAdapter { public options: OpacityOptions; + private eigenDAClient: InstanceType; + private eigenDAIdentifier: Uint8Array; constructor(options: OpacityOptions) { this.options = options; + + // Initialize EigenDA client if private key is provided + if (options.eigenDAPrivateKey) { + this.eigenDAClient = new EigenDAClient({ + privateKey: options.eigenDAPrivateKey, + apiUrl: options.eigenDAApiUrl, + rpcUrl: options.eigenDARpcUrl, + creditsContractAddress: options.eigenDACreditsContractAddress + }); + } + } + + private async initializeEigenDA() { + if (!this.eigenDAClient) { + throw new Error("EigenDA client not initialized - missing private key"); + } + + if (!this.eigenDAIdentifier) { + // Get or create identifier + const identifiers = await this.eigenDAClient.getIdentifiers(); + this.eigenDAIdentifier = identifiers.length > 0 + ? identifiers[0] + : await this.eigenDAClient.createIdentifier(); + + // Check balance and top up if needed + const balance = await this.eigenDAClient.getBalance(this.eigenDAIdentifier); + if (balance < 0.001) { + elizaLogger.log("EigenDA balance low, topping up with 0.01 ETH..."); + await this.eigenDAClient.topupCredits(this.eigenDAIdentifier, 0.01); + } + } } async generateText( @@ -133,6 +173,7 @@ export class OpacityAdapter implements IVerifiableInferenceAdapter { this.options.opacityProverUrl, cloudflareLogId ); + elizaLogger.debug( "Proof generated for text generation ID:", cloudflareLogId @@ -160,7 +201,36 @@ export class OpacityAdapter implements IVerifiableInferenceAdapter { if (!response.ok) { throw new Error(`Failed to fetch proof: ${response.statusText}`); } - return await response.json(); + const proof = await response.json(); + + // Store proof in EigenDA if client is initialized + if (this.eigenDAClient) { + try { + await this.initializeEigenDA(); + + // Store proof with metadata + const proofData = JSON.stringify({ + proof, + logId, + timestamp: Date.now() + }); + + const uploadResult = await this.eigenDAClient.upload(proofData, this.eigenDAIdentifier); + elizaLogger.debug("Proof stored in EigenDA with job ID:", uploadResult.job_id); + + // Return proof with EigenDA reference + return { + ...proof, + eigenDAJobId: uploadResult.job_id + }; + } catch (error) { + elizaLogger.error("Failed to store proof in EigenDA:", error); + // Return original proof if EigenDA storage fails + return proof; + } + } + + return proof; } async verifyProof(result: VerifiableInferenceResult): Promise { @@ -169,7 +239,7 @@ export class OpacityAdapter implements IVerifiableInferenceAdapter { result.id, result.proof ); - console.log("Proof is valid:", isValid.success); + elizaLogger.log("Proof verified:", isValid.success); if (!isValid.success) { throw new Error("Proof is invalid"); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1459a8f7728..f1327e9ad9b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -292,6 +292,9 @@ importers: '@elizaos/plugin-echochambers': specifier: workspace:* version: link:../packages/plugin-echochambers + '@elizaos/plugin-eigenda': + specifier: workspace:* + version: link:../packages/plugin-eigenda '@elizaos/plugin-email': specifier: workspace:* version: link:../packages/plugin-email @@ -1068,13 +1071,13 @@ importers: dependencies: '@discordjs/opus': specifier: github:discordjs/opus - version: https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda(encoding@0.1.13) + version: https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2(encoding@0.1.13) '@discordjs/rest': specifier: 2.4.0 version: 2.4.0 '@discordjs/voice': specifier: 0.17.0 - version: 0.17.0(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda(encoding@0.1.13))(bufferutil@4.0.9)(ffmpeg-static@5.2.0)(utf-8-validate@6.0.5) + version: 0.17.0(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2(encoding@0.1.13))(bufferutil@4.0.9)(ffmpeg-static@5.2.0)(utf-8-validate@6.0.5) '@elizaos/core': specifier: workspace:* version: link:../core @@ -1089,7 +1092,7 @@ importers: version: 0.7.15 prism-media: specifier: 1.3.5 - version: 1.3.5(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda(encoding@0.1.13))(ffmpeg-static@5.2.0) + version: 1.3.5(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2(encoding@0.1.13))(ffmpeg-static@5.2.0) whatwg-url: specifier: 7.1.0 version: 7.1.0 @@ -2058,6 +2061,9 @@ importers: tsup: specifier: 8.3.5 version: 8.3.5(@swc/core@1.10.11(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0) + vitest: + specifier: ^1.2.1 + version: 1.2.1(@types/node@22.12.0)(jsdom@25.0.1(bufferutil@4.0.9)(canvas@2.11.2(encoding@0.1.13))(utf-8-validate@6.0.5))(terser@5.37.0) packages/plugin-autonome: dependencies: @@ -2548,6 +2554,34 @@ importers: specifier: workspace:* version: link:../plugin-node + packages/plugin-eigenda: + dependencies: + '@elizaos/core': + specifier: workspace:* + version: link:../core + axios: + specifier: ^1.6.7 + version: 1.7.9 + ethers: + specifier: ^6.11.1 + version: 6.13.4(bufferutil@4.0.9)(utf-8-validate@6.0.5) + zod: + specifier: ^3.22.4 + version: 3.23.8 + devDependencies: + '@types/node': + specifier: ^20.11.19 + version: 20.17.9 + rimraf: + specifier: ^5.0.5 + version: 5.0.10 + tsup: + specifier: ^8.0.2 + version: 8.3.5(@swc/core@1.10.11(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.6.3)(yaml@2.7.0) + typescript: + specifier: ^5.3.3 + version: 5.6.3 + packages/plugin-email: dependencies: '@elizaos/adapter-postgres': @@ -3881,6 +3915,9 @@ importers: '@elizaos/core': specifier: workspace:* version: link:../core + '@elizaos/plugin-eigenda': + specifier: workspace:* + version: link:../plugin-eigenda dotenv: specifier: ^16.4.5 version: 16.4.7 @@ -6931,8 +6968,8 @@ packages: resolution: {integrity: sha512-YJOVVZ545x24mHzANfYoy0BJX5PDyeZlpiJjDkUBM/V/Ao7TFX9lcUvCN4nr0tbr5ubeaXxtEBILUrHtTphVeQ==} hasBin: true - '@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda': - resolution: {tarball: https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda} + '@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2': + resolution: {tarball: https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2} version: 0.10.0 engines: {node: '>=12.0.0'} @@ -32343,7 +32380,7 @@ snapshots: - encoding - supports-color - '@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda(encoding@0.1.13)': + '@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2(encoding@0.1.13)': dependencies: '@discordjs/node-pre-gyp': 0.4.5(encoding@0.1.13) node-addon-api: 8.3.0 @@ -32365,11 +32402,11 @@ snapshots: '@discordjs/util@1.1.1': {} - '@discordjs/voice@0.17.0(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda(encoding@0.1.13))(bufferutil@4.0.9)(ffmpeg-static@5.2.0)(utf-8-validate@6.0.5)': + '@discordjs/voice@0.17.0(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2(encoding@0.1.13))(bufferutil@4.0.9)(ffmpeg-static@5.2.0)(utf-8-validate@6.0.5)': dependencies: '@types/ws': 8.5.14 discord-api-types: 0.37.83 - prism-media: 1.3.5(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda(encoding@0.1.13))(ffmpeg-static@5.2.0) + prism-media: 1.3.5(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2(encoding@0.1.13))(ffmpeg-static@5.2.0) tslib: 2.8.1 ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@6.0.5) transitivePeerDependencies: @@ -61298,9 +61335,9 @@ snapshots: extend-shallow: 2.0.1 js-beautify: 1.15.1 - prism-media@1.3.5(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda(encoding@0.1.13))(ffmpeg-static@5.2.0): + prism-media@1.3.5(@discordjs/opus@https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2(encoding@0.1.13))(ffmpeg-static@5.2.0): optionalDependencies: - '@discordjs/opus': https://codeload.github.com/discordjs/opus/tar.gz/18cedf3292fe634f99f81af4a409389dc7b1ebda(encoding@0.1.13) + '@discordjs/opus': https://codeload.github.com/discordjs/opus/tar.gz/679ff3f58e6804b80becc166c7214deb2ca026e2(encoding@0.1.13) ffmpeg-static: 5.2.0 prism-react-renderer@2.3.1(react@18.3.1):