From fd2982d1afacd6bf89084324b478ec04af18052e Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 23 May 2024 10:56:44 -0400 Subject: [PATCH 01/25] release/v4.9.0 (#7057) * update changelog and bump versions * update changelog and revert version bump web3-types * change web3-eth-abi package version --- CHANGELOG.md | 22 +++++++++++++++++++++- packages/web3-core/CHANGELOG.md | 7 ++++++- packages/web3-core/package.json | 12 ++++++------ packages/web3-errors/CHANGELOG.md | 6 ++++-- packages/web3-errors/package.json | 4 ++-- packages/web3-eth-abi/CHANGELOG.md | 6 ++++++ packages/web3-eth-abi/package.json | 8 ++++---- packages/web3-eth-contract/CHANGELOG.md | 4 +++- packages/web3-eth-contract/package.json | 14 +++++++------- packages/web3-eth-ens/CHANGELOG.md | 5 ++++- packages/web3-eth-ens/package.json | 18 +++++++++--------- packages/web3-eth/CHANGELOG.md | 4 +++- packages/web3-eth/package.json | 16 ++++++++-------- packages/web3-net/CHANGELOG.md | 5 ++++- packages/web3-net/package.json | 10 +++++----- packages/web3-rpc-methods/CHANGELOG.md | 4 +++- packages/web3-rpc-methods/package.json | 8 ++++---- packages/web3-types/CHANGELOG.md | 2 +- packages/web3-utils/CHANGELOG.md | 4 +++- packages/web3-utils/package.json | 6 +++--- packages/web3-validator/CHANGELOG.md | 6 ++++-- packages/web3-validator/package.json | 6 +++--- packages/web3/CHANGELOG.md | 4 +++- packages/web3/package.json | 22 +++++++++++----------- packages/web3/src/version.ts | 2 +- 25 files changed, 128 insertions(+), 77 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94a802644cc..b756bba2604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2444,7 +2444,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Added `signature` to type `AbiFunctionFragment` (#6922) - update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) -## [Unreleased] +## [4.9.0] ### Added @@ -2456,6 +2456,10 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - `defaultReturnFormat` was added to the configuration options. (#6947) +#### web3-errors + +- Added `InvalidIntegerError` error for fromWei and toWei (#7052) + #### web3-eth - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) @@ -2480,6 +2484,8 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-utils +- `toWei` add warning when using large numbers or large decimals that may cause precision loss (#6908) +- `toWei` and `fromWei` now supports integers as a unit. (#7053) ### Fixed @@ -2489,9 +2495,17 @@ If there are any bugs, improvements, optimizations or any new feature proposal f #### web3-utils +- `toWei` support numbers in scientific notation (#6908) +- `toWei` and `fromWei` trims according to ether unit successfuly (#7044) #### web3-validator +- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. (#6981) +- `browser` entry point that was pointing to an non-existing bundle file was removed from `package.json` (#7015) + +#### web3-core + +- Set a try catch block if processesingError fails (#7022) ### Changed @@ -2504,6 +2518,12 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Added parameter `customTransactionReceiptSchema` into methods `emitConfirmation`, `waitForTransactionReceipt`, `watchTransactionByPolling`, `watchTransactionBySubscription`, `watchTransactionForConfirmations` (#7000) - Changed functionality: For networks that returns `baseFeePerGas===0x0` fill `maxPriorityFeePerGas` and `maxFeePerGas` by `getGasPrice` method (#7050) +#### web3-eth-abi + +- Dependencies updated + #### web3-rpc-methods - Change `estimateGas` method to add possibility pass Transaction type (#7000) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index d69e71c8cf9..0346e3f74a9 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -207,7 +207,7 @@ Documentation: - Web3config `contractDataInputFill` has been defaulted to `data`, istead of `input`. (#6622) -## [Unreleased] +## [4.4.0] ### Added @@ -217,3 +217,8 @@ Documentation: - Interface `RequestManagerMiddleware` was changed (#7003) +### Fixed + +- Set a try catch block if processesingError fails (#7022) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index 04fcb06f509..865aafd0db6 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -1,6 +1,6 @@ { "name": "web3-core", - "version": "4.3.2", + "version": "4.4.0", "description": "Web3 core tools for sub-packages. This is an internal package.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -42,14 +42,14 @@ "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" }, "dependencies": { - "web3-errors": "^1.1.4", + "web3-errors": "^1.2.0", + "web3-eth-accounts": "^4.1.2", "web3-eth-iban": "^4.0.7", - "web3-eth-accounts": "^4.1.0", "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.0", - "web3-validator": "^2.0.3" + "web3-types": "^1.6.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "optionalDependencies": { "web3-providers-ipc": "^4.0.7" diff --git a/packages/web3-errors/CHANGELOG.md b/packages/web3-errors/CHANGELOG.md index 2acbb60bc4f..7f9b132283b 100644 --- a/packages/web3-errors/CHANGELOG.md +++ b/packages/web3-errors/CHANGELOG.md @@ -166,8 +166,10 @@ Documentation: - Fixed grammar and spelling in `transactionTimeoutHint` (#6559) -## [Unreleased] +## [1.2.0] ### Added -- Added `InvalidIntegerError` error for fromWei and toWei (#7052) \ No newline at end of file +- Added `InvalidIntegerError` error for fromWei and toWei (#7052) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-errors/package.json b/packages/web3-errors/package.json index 08a2b5ebb7f..1b8587c81b3 100644 --- a/packages/web3-errors/package.json +++ b/packages/web3-errors/package.json @@ -1,6 +1,6 @@ { "name": "web3-errors", - "version": "1.1.4", + "version": "1.2.0", "description": "This package has web3 error classes", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -41,7 +41,7 @@ "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" }, "dependencies": { - "web3-types": "^1.3.1" + "web3-types": "^1.6.0" }, "devDependencies": { "@types/jest": "^28.1.6", diff --git a/packages/web3-eth-abi/CHANGELOG.md b/packages/web3-eth-abi/CHANGELOG.md index 47f57f4d2a4..4a7f1fe8add 100644 --- a/packages/web3-eth-abi/CHANGELOG.md +++ b/packages/web3-eth-abi/CHANGELOG.md @@ -170,4 +170,10 @@ Documentation: - Dependencies updated +## [4.2.2] + +### Changed + +- Dependencies updated + ## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-abi/package.json b/packages/web3-eth-abi/package.json index 1ed38b13f05..4333ba616bb 100644 --- a/packages/web3-eth-abi/package.json +++ b/packages/web3-eth-abi/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-abi", - "version": "4.2.1", + "version": "4.2.2", "description": "Web3 module encode and decode EVM in/output.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -43,10 +43,10 @@ }, "dependencies": { "abitype": "0.7.1", - "web3-errors": "^1.1.4", + "web3-errors": "^1.2.0", "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "devDependencies": { "@humeris/espresso-shot": "^4.0.0", diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 8aa7c126ebb..8e275470925 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -380,8 +380,10 @@ Documentation: - Added a console warning in case of an ambiguous call to a solidity method with parameter overloading (#6942) - Added contract.deploy(...).decodeData(...) and contract.decodeMethodData(...) that decode data based on the ABI (#6950) -## [Unreleased] +## [4.5.0] ### Added - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-contract/package.json b/packages/web3-eth-contract/package.json index 0c8cd166675..74edee8f90b 100644 --- a/packages/web3-eth-contract/package.json +++ b/packages/web3-eth-contract/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-contract", - "version": "4.4.0", + "version": "4.5.0", "description": "Web3 module to interact with Ethereum smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -45,13 +45,13 @@ "test:e2e:firefox": "npx cypress run --headless --browser firefox --env grep='ignore',invert=true" }, "dependencies": { - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.6.0", - "web3-eth-abi": "^4.2.1", + "web3-core": "^4.4.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.7.0", + "web3-eth-abi": "^4.2.2", "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "devDependencies": { "@humeris/espresso-shot": "^4.0.0", diff --git a/packages/web3-eth-ens/CHANGELOG.md b/packages/web3-eth-ens/CHANGELOG.md index c40b2727d5e..c9be2f93561 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -153,7 +153,10 @@ Documentation: - Added function getText and getName in ENS and resolver classes (#6914) -## [Unreleased] +## [4.3.0] ### Added + - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-ens/package.json b/packages/web3-eth-ens/package.json index db7fc9d2d03..4c1865ca983 100644 --- a/packages/web3-eth-ens/package.json +++ b/packages/web3-eth-ens/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-ens", - "version": "4.2.0", + "version": "4.3.0", "description": "This package has ENS functions for interacting with Ethereum Name Service.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -59,13 +59,13 @@ }, "dependencies": { "@adraffy/ens-normalize": "^1.8.8", - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.5.0", - "web3-eth-contract": "^4.3.0", - "web3-net": "^4.0.7", - "web3-types": "^1.5.0", - "web3-utils": "^4.2.2", - "web3-validator": "^2.0.5" + "web3-core": "^4.4.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.7.0", + "web3-eth-contract": "^4.5.0", + "web3-net": "^4.1.0", + "web3-types": "^1.6.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 01294d0b449..3d2d36b17c0 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -232,7 +232,7 @@ Documentation: - method `getBlock` now includes properties of eip 4844, 4895, 4788 when returning block (#6933) - update type `withdrawalsSchema`, `blockSchema` and `blockHeaderSchema` schemas to include properties of eip 4844, 4895, 4788 (#6933) -## [Unreleased] +## [4.7.0] ### Added @@ -247,3 +247,5 @@ Documentation: ### Fixed - Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 767f5697387..47c188743b2 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.6.0", + "version": "4.7.0", "description": "Web3 module to interact with the Ethereum blockchain and smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -63,15 +63,15 @@ }, "dependencies": { "setimmediate": "^1.0.5", - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth-abi": "^4.2.1", + "web3-core": "^4.4.0", + "web3-errors": "^1.2.0", + "web3-eth-abi": "^4.2.2", "web3-eth-accounts": "^4.1.2", - "web3-net": "^4.0.7", + "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-rpc-methods": "^1.2.0", + "web3-rpc-methods": "^1.3.0", "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-net/CHANGELOG.md b/packages/web3-net/CHANGELOG.md index d60abde6313..5e7ea9073b3 100644 --- a/packages/web3-net/CHANGELOG.md +++ b/packages/web3-net/CHANGELOG.md @@ -141,7 +141,10 @@ Documentation: - Dependencies updated -## [Unreleased] +## [4.1.0] ### Added + - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-net/package.json b/packages/web3-net/package.json index d3ca4f5a32b..952457f72be 100644 --- a/packages/web3-net/package.json +++ b/packages/web3-net/package.json @@ -1,6 +1,6 @@ { "name": "web3-net", - "version": "4.0.7", + "version": "4.1.0", "description": "Web3 module to interact with the Ethereum nodes networking properties.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -56,9 +56,9 @@ "typescript": "^4.7.4" }, "dependencies": { - "web3-core": "^4.3.0", - "web3-rpc-methods": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7" + "web3-core": "^4.4.0", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.6.0", + "web3-utils": "^4.3.0" } } diff --git a/packages/web3-rpc-methods/CHANGELOG.md b/packages/web3-rpc-methods/CHANGELOG.md index c57997c5ddc..050b6451539 100644 --- a/packages/web3-rpc-methods/CHANGELOG.md +++ b/packages/web3-rpc-methods/CHANGELOG.md @@ -138,8 +138,10 @@ Documentation: - Added `getMaxPriorityFeePerGas` method (#6748) -## [Unreleased] +## [1.3.0] ### Changed - Change `estimateGas` method to add possibility pass Transaction type (#7000) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-rpc-methods/package.json b/packages/web3-rpc-methods/package.json index 8e9eec0e597..3a05060f2c2 100644 --- a/packages/web3-rpc-methods/package.json +++ b/packages/web3-rpc-methods/package.json @@ -1,6 +1,6 @@ { "name": "web3-rpc-methods", - "version": "1.2.0", + "version": "1.3.0", "description": "Ethereum RPC methods for Web3 4.x.x", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -56,8 +56,8 @@ "typescript": "^4.7.4" }, "dependencies": { - "web3-core": "^4.3.2", - "web3-types": "^1.5.0", - "web3-validator": "^2.0.4" + "web3-core": "^4.4.0", + "web3-types": "^1.6.0", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 3f96fe9d53d..638d9616377 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -189,7 +189,7 @@ Documentation: - Type `FeeData` to be filled by `await web3.eth.calculateFeeData()` to be used with EIP-1559 transactions (#6795) -## [Unreleased] +## [1.6.0] ### Added diff --git a/packages/web3-utils/CHANGELOG.md b/packages/web3-utils/CHANGELOG.md index 763f7f1d462..5fcf44ccec5 100644 --- a/packages/web3-utils/CHANGELOG.md +++ b/packages/web3-utils/CHANGELOG.md @@ -216,7 +216,7 @@ Documentation: - fixed toHex incorrectly hexing Uint8Arrays and Buffer (#6957) - fixed isUint8Array not returning true for Buffer (#6957) -## [Unreleased] +## [4.3.0] ### Added @@ -227,3 +227,5 @@ Documentation: - `toWei` support numbers in scientific notation (#6908) - `toWei` and `fromWei` trims according to ether unit successfuly (#7044) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-utils/package.json b/packages/web3-utils/package.json index 511ce216fc2..c07e9b85821 100644 --- a/packages/web3-utils/package.json +++ b/packages/web3-utils/package.json @@ -1,7 +1,7 @@ { "name": "web3-utils", "sideEffects": false, - "version": "4.2.3", + "version": "4.3.0", "description": "Collection of utility functions used in web3.js.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -65,8 +65,8 @@ "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", + "web3-errors": "^1.2.0", "web3-types": "^1.6.0", - "web3-validator": "^2.0.5" + "web3-validator": "^2.0.6" } } diff --git a/packages/web3-validator/CHANGELOG.md b/packages/web3-validator/CHANGELOG.md index ea8cd0259ff..da4cc2c0136 100644 --- a/packages/web3-validator/CHANGELOG.md +++ b/packages/web3-validator/CHANGELOG.md @@ -168,9 +168,11 @@ Documentation: - Multi-dimensional arrays(with a fix length) are now handled properly when parsing ABIs (#6798) -## [Unreleased] +## [2.0.6] ### Fixed -- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. +- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. (#6981) - `browser` entry point that was pointing to an non-existing bundle file was removed from `package.json` (#7015) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-validator/package.json b/packages/web3-validator/package.json index c416a1fa235..4a12b604981 100644 --- a/packages/web3-validator/package.json +++ b/packages/web3-validator/package.json @@ -1,6 +1,6 @@ { "name": "web3-validator", - "version": "2.0.5", + "version": "2.0.6", "description": "JSON-Schema compatible validator for web3", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -46,8 +46,8 @@ "dependencies": { "ethereum-cryptography": "^2.0.0", "util": "^0.12.5", - "web3-errors": "^1.1.4", - "web3-types": "^1.5.0", + "web3-errors": "^1.2.0", + "web3-types": "^1.6.0", "zod": "^3.21.4" }, "devDependencies": { diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 15fca59a531..896d0d884f0 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -262,8 +262,10 @@ Documentation: - Added `signature` to type `AbiFunctionFragment` (#6922) - update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) -## [Unreleased] +## [4.9.0] ### Added - Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3/package.json b/packages/web3/package.json index 52bb78ce8c8..668d77e26ff 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.8.0", + "version": "4.9.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -86,21 +86,21 @@ "web3-providers-ipc": "^4.0.7" }, "dependencies": { - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.6.0", - "web3-eth-abi": "^4.2.1", + "web3-core": "^4.4.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.7.0", + "web3-eth-abi": "^4.2.2", "web3-eth-accounts": "^4.1.2", - "web3-eth-contract": "^4.4.0", - "web3-eth-ens": "^4.2.0", + "web3-eth-contract": "^4.5.0", + "web3-eth-ens": "^4.3.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.0.8", - "web3-net": "^4.0.7", + "web3-net": "^4.1.0", "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-rpc-methods": "^1.2.0", + "web3-rpc-methods": "^1.3.0", "web3-types": "^1.6.0", - "web3-utils": "^4.2.3", - "web3-validator": "^2.0.5" + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" } } diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index 8e4910766d8..4ab9622dba7 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.8.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.9.0' }; From 7537f03db3a2932a4f5c6f13ada1c3d6ca0217cd Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Thu, 23 May 2024 08:32:25 -0700 Subject: [PATCH 02/25] fix(docs): intro (#7056) * fix(docs): intro - landing page should be Introduction as opposed to Quickstart - improvements to Introduction * Packages Enhancements to package documentation * Tweaks * @luu-alex suggestion * Update docs/docs/guides/getting_started/introduction.md Co-authored-by: Alex --------- Co-authored-by: Alex --- .../guides/getting_started/introduction.md | 66 ++++++++++--------- .../{getting_started.md => quickstart.md} | 1 - 2 files changed, 35 insertions(+), 32 deletions(-) rename docs/docs/guides/getting_started/{getting_started.md => quickstart.md} (99%) diff --git a/docs/docs/guides/getting_started/introduction.md b/docs/docs/guides/getting_started/introduction.md index ab9a303fc84..0e92051b4ce 100644 --- a/docs/docs/guides/getting_started/introduction.md +++ b/docs/docs/guides/getting_started/introduction.md @@ -1,66 +1,70 @@ --- +slug: / sidebar_position: 1 sidebar_label: Introduction --- # Introduction -Welcome to Web3.js Documentation!👋 +Web3.js is a robust and flexible collection of **TypeScript and JavaScript** libraries that allows developers to interact with local or remote [Ethereum](https://ethereum.org/en/) nodes (or **any EVM-compatible blockchain**) over **HTTP, IPC or WebSocket** connections. It is a powerful and efficient toolkit for crafting applications within the Ethereum ecosystem and beyond. -Web3.js is a robust and flexible collection of libraries for **TypeScript and JavaScript** developers. It allows you to interact with a local or remote Ethereum node (or **any EVM-compatible blockchain**) using **HTTP, IPC or WebSocket.** It serves as an essential tool for connecting and crafting applications within the Ethereum ecosystem. - -The following documentation will guide you through different use cases of Web3.js, upgrading from older versions, as well as providing an API reference documentation with examples. +This documentation is the entrypoint to Web3.js for developers. It covers [basic](/guides/getting_started/quickstart) and [advanced](/guides/smart_contracts/) usage with examples, and includes comprehensive [API documentation](/api) as well as guides for common tasks, like [upgrading](/guides/web3_upgrade_guide/x/) from older versions. ## Features of Web3.js v4 -- Web3.js [Plugins Feature](/guides/web3_plugin_guide/) for extending functionality ( [List of Existing Plugins](https://web3js.org/plugins) ) -- ECMAScript (ESM) and CommonJS (CJS) builds -- [Tree shakable with ESM](/guides/advanced/tree_shaking) -- [Contracts dynamic types](/guides/smart_contracts/infer_contract_types/) & full API in TypeScript -- Using native BigInt instead of large BigNumber libraries -- More efficient ABI Encoder & Decoder -- Custom Output formatters -- In compliance with Eth EL API +- Flexible + - ECMAScript (ESM) and CommonJS (CJS) builds + - [Plugins](/guides/web3_plugin_guide/) for extending functionality +- Efficient + - Modular, [package](/#packages)-based design reduces unneeded dependencies + - [Tree shakable with ESM](/guides/advanced/tree_shaking) + - Use of native [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (instead of large [BigNumber](https://mikemcl.github.io/bignumber.js/) libraries) + - Efficient ABI [encoding](/api/web3-eth-abi/function/encodeFunctionCall) & [decoding](/api/web3-eth-abi/function/decodeParameter) +- Developer-Friendly + - [Dynamic contract types](/guides/smart_contracts/infer_contract_types/) & full API in TypeScript + - Custom output [formatters](https://docs.web3js.org/api/web3-utils/function/format) + - In compliance with the [Ethereum JSON-RPC Specification](https://ethereum.github.io/execution-apis/api-documentation/) ## Packages -Web3.js is modular, consisting of several packages, each serving specific functionalities. If you have specific tasks in mind, you don't need to install the entire Web3 library. Instead, selectively install the package that suits your requirements for a more efficient development experience. Here is an overview of the available packages: +Web3.js is a modular collection of packages, each of which serves a specific needs. This means developers don't need to install the entire Web3 library for most use cases. Instead, necessary packages are selectively installed for a more efficient development experience. Here is an overview of a selection of available packages: + +- [**Web3Eth:**](/libdocs/Web3Eth) The `web3-eth` package is the entrypoint to Web3.js - it's the control center for managing interactions with Ethereum and other EVM-compatible networks. -- [**ABI:**](/libdocs/ABI) The `web3-eth-abi` package simplifies decoding logs and parameters, encoding function calls and signatures, and inferring types for efficient Ethereum **contract interactions.** +- [**Net:**](/libdocs/Net) The `web3-net` package provides discovery and interactions for an **Ethereum node's network properties.** -- [**Accounts:**](/libdocs/Accounts) The `web3-eth-accounts` package has tools for creating Ethereum accounts/wallets and making sure transactions and data are **securely signed.** +- [**Accounts:**](/libdocs/Accounts) The `web3-eth-accounts` package has tools for creating Ethereum accounts and the **secure signing** of transactions and data. -- [**Contract:**](/libdocs/Contract) With the `web3-eth-Contract`, you can interact with Smart contracts. This functionality allows **communication with contracts through JavaScript or TypeScript objects**, simplifying your development and interaction processes. +- [**Personal:**](/libdocs/Personal) Use `web3-eth-personal` for **direct communication about your accounts with the Ethereum node**, which streamlines account management during development. -- [**ENS:**](/libdocs/ENS) The `web3-eth-ens` package helps you communicate with the **Ethereum Name Service (ENS)** on the blockchain. + **NOTE:** *For enhanced security in production and when interacting with public nodes, consider using `web3-eth-accounts` for local signing operations, which keeps your private keys and sensitive information secure on your local machine* -- [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN). It makes the conversion back and forth easier. +- [**Utils:**](/libdocs/Utils) The `web3-utils` package provides helpers to perform a range of essential Ethereum development tasks, including **converting data formats, checking addresses, encoding and decoding data, hashing, handling numbers, and much more.**. -- [**Net:**](/libdocs/Net) The `web3-net` class allows you to talk about and deal with an **Ethereum node's network details.** +- [**Contract:**](/libdocs/Contract) The `web3-eth-contract` package makes it easy to **interact with smart contracts through JavaScript or TypeScript,** which streamlines the development process and makes it less error-prone. -- [**Personal:**](/libdocs/Personal) Use `web3-eth-personal` for **direct communication with the Ethereum node about your accounts**, streamlining account management in your development workflow. - **NOTE:** *For enhanced security when interacting with public nodes, consider using `web3-eth-accounts` for local signing operations, keeping your private keys and sensitive information secure on your local machine* +- [**ABI:**](/libdocs/ABI) The `web3-eth-abi` package simplifies decoding logs and parameters, encoding function calls and signatures, and inferring types for efficient Ethereum **smart contract interactions.** -- [**Utils:**](/libdocs/Utils) With the `web3-utils` package you can perform a range of essential tasks in Ethereum development, including **converting data formats, checking addresses, encoding and decoding, hashing, handling numbers, and much more**, providing versatile utility functions for your applications. +- [**ENS:**](/libdocs/ENS) The `web3-eth-ens` package makes it easy for developers to communicate with the **Ethereum Name Service (ENS).** -- [**Web3Eth:**](/libdocs/Web3Eth) The `web3-eth` is your main tool for interacting with the Ethereum blockchain. It's like the control center for managing your interactions with Ethereum. +- [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN) and simplifies conversion between the types. -### Additional supporting packages +### Additional supporting packages -- **Web3 Types:** This package has common typescript types. +- [**Web3 Core:**](/api/web3-core) subscriptions, request management, and configuration used by other Web3 packages -- **Web3 Validator:** This package offers functionality for validation using provided Schema. +- [**Web3 Types:**](/api/web3-types) data structures, objects, interfaces and types used by Web3 -- **Web3 Core:** Web3 Core has configuration, Subscriptions and Requests management functionality used by other Web3 packages. +- [**Web3 Validator:**](/api/web3-validator) runtime type validation against predefined types or custom schemas -- **Web3 Errors:** Web3 Errors has error codes and common error classes that are used by other Web3 packages. +- [**Web3 Errors:**](/api/web3-errors) error codes and common error classes that are used by other Web3 packages -- **Web3 RPC Methods:** This is for advanced uses for building more lightweight applications. It has functions for making RPC requests to Ethereum using a given provider. +- [**Web3 RPC Methods:**](/api/web3/namespace/rpcMethods) functions for making RPC requests to Ethereum using a given provider ## Advantages over other libraries -- **Extensive Documentation and Community**: Being one of the earliest Ethereum libraries, Web3.js benefits from extensive documentation and a large, active community. Web3.js is widely adopted and has been thoroughly tested in various production environments and is compatible with a broad range of other tools and services in the Ethereum ecosystem. +- **Extensive Documentation and Community**: Web3.js is one of the most established Ethereum libraries, which means it benefits from extensive documentation and a large, active community. Web3.js is widely adopted and has been thoroughly tested in various production environments, and is compatible with a broad range of other tools and services in the Ethereum ecosystem. -- **Modular Design**: Web3.js is designed to be modular, meaning it allows developers to use specific packages according to their needs. This may lead to smaller bundle sizes and faster load times for web applications. +- **Modular Design**: Web3.js is designed to be modular, which allows developers to use specific packages according to their needs. This leads to smaller bundle sizes and faster load times for web applications. - **Active Development and Support**: Web3.js sees regular updates and active development. This support is crucial for developers needing assurance that the library they're using will keep pace with the evolving Ethereum landscape. diff --git a/docs/docs/guides/getting_started/getting_started.md b/docs/docs/guides/getting_started/quickstart.md similarity index 99% rename from docs/docs/guides/getting_started/getting_started.md rename to docs/docs/guides/getting_started/quickstart.md index 18b95035957..d023e01bb9f 100644 --- a/docs/docs/guides/getting_started/getting_started.md +++ b/docs/docs/guides/getting_started/quickstart.md @@ -1,5 +1,4 @@ --- -slug: / sidebar_position: 2 sidebar_label: Quickstart --- From 692987a78dc1690bcd3917c4ff3b3264e6a35274 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Fri, 24 May 2024 15:43:47 +0200 Subject: [PATCH 03/25] coverage increase (#7051) * coverage increase * get Uncle tests * lint err fix * correction --- ...as.ts => get_maxPriorityFeePerGas.test.ts} | 0 .../get_uncle_by_block_number.test.ts | 42 +++++ .../personal_rpc_methods/eth_personal.test.ts | 145 ++++++++++++++++++ 3 files changed, 187 insertions(+) rename packages/web3-rpc-methods/test/unit/eth_rpc_methods/{get_maxPriorityFeePerGas.ts => get_maxPriorityFeePerGas.test.ts} (100%) create mode 100644 packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts create mode 100644 packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts diff --git a/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.ts b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.test.ts similarity index 100% rename from packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.ts rename to packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_maxPriorityFeePerGas.test.ts diff --git a/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts new file mode 100644 index 00000000000..93e8a633582 --- /dev/null +++ b/packages/web3-rpc-methods/test/unit/eth_rpc_methods/get_uncle_by_block_number.test.ts @@ -0,0 +1,42 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { Web3RequestManager } from 'web3-core'; +import { ethRpcMethods } from '../../../src/index'; + +jest.mock('web3-validator'); + +describe('getUncleByBlockNumberAndIndex', () => { + let requestManagerSendSpy: jest.Mock; + let requestManager: Web3RequestManager; + + beforeAll(() => { + requestManager = new Web3RequestManager('http://127.0.0.1:8545'); + requestManagerSendSpy = jest.fn(); + requestManager.send = requestManagerSendSpy; + }); + + it('should call requestManager.send with eth_getUncleByBlockNumberAndIndex method', async () => { + await ethRpcMethods.getUncleByBlockNumberAndIndex(requestManager, 0, '1' ); + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'eth_getUncleByBlockNumberAndIndex', + params: [0,'1'], + }); + }, + ); + +}); diff --git a/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts b/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts new file mode 100644 index 00000000000..a487df07964 --- /dev/null +++ b/packages/web3-rpc-methods/test/unit/personal_rpc_methods/eth_personal.test.ts @@ -0,0 +1,145 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { Web3RequestManager } from 'web3-core'; +import { EthPersonalAPI } from 'web3-types'; +import { personalRpcMethods } from '../../../src/index'; + +describe('Eth Personal', () => { + let requestManagerSendSpy: jest.Mock; + let requestManager: Web3RequestManager; + + beforeAll(() => { + requestManager = new Web3RequestManager('http://127.0.0.1:8545'); + requestManagerSendSpy = jest.fn(); + requestManager.send = requestManagerSendSpy; + }); + + it('should call requestManager.send with personal_listAccounts method', async () => { + await personalRpcMethods.getAccounts(requestManager); + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_listAccounts', + params: [], + }); + }); + + it('should call requestManager.send with personal_newAccount method', async () => { + const pass = "ABC123"; + await personalRpcMethods.newAccount(requestManager, pass); + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_newAccount', + params: [pass], + }); + }); + + it('should call requestManager.send with personal_unlockAccount method', async () => { + const pass = "ABC123"; + const address = "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789"; + const duration = 100; + await personalRpcMethods.unlockAccount(requestManager, address, pass, duration); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_unlockAccount', + params: [address, pass, duration], + }); + }); + + it('should call requestManager.send with personal_lockAccount method', async () => { + const address = "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789"; + + await personalRpcMethods.lockAccount(requestManager, address ); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_lockAccount', + params: [address], + }); + }); + + it('should call requestManager.send with personal_importRawKey method', async () => { + const passPhrase = "123456"; + const keyData = "abe40cb08850da918ee951b237fa87946499b2d8643e4aa12b0610b050c731f6"; + await personalRpcMethods.importRawKey(requestManager, keyData, passPhrase ); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_importRawKey', + params: [keyData,passPhrase], + }); + }); + + it('should call requestManager.send with personal_sendTransaction method', async () => { + const passPhrase = "123456"; + const tx = { + from: "0x0d4aa485ecbc499c70860feb7e5aaeaf5fd8172e", + gasPrice: "20000", + gas: "21000", + to: "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789", + value: "1000000", + data: "", + nonce: 0, + }; + await personalRpcMethods.sendTransaction(requestManager, tx, passPhrase ); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_sendTransaction', + params: [tx,passPhrase], + }); + }); + + it('should call requestManager.send with personal_signTransaction method', async () => { + const passPhrase = "123456"; + const tx = { + from: "0x0d4aa485ecbc499c70860feb7e5aaeaf5fd8172e", + gasPrice: "20000", + gas: "21000", + to: "0x4106486FB42F3Abf07CC07ef5DEE38f60319e789", + value: "1000000", + data: "", + nonce: 0, + }; + await personalRpcMethods.signTransaction(requestManager, tx, passPhrase ); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_signTransaction', + params: [tx,passPhrase], + }); + }); + + it('should call requestManager.send with personal_sign method', async () => { + const data = "Hello world"; + const address = "0x0D4Aa485ECbC499c70860fEb7e5AaeAf5fd8172E"; + const pass = "123456"; + + await personalRpcMethods.sign(requestManager, data,address,pass); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_sign', + params: [ data,address,pass], + }); + }); + + it('should call requestManager.send with personal_ecRecover method', async () => { + const data = "Hello world"; + const signature = "0x5d21d01b3198ac34d0585a9d76c4d1c8123e5e06746c8962318a1c08ffb207596e6fce4a6f377b7c0fc98c5f646cd73438c80e8a1a95cbec55a84c2889dca0301b"; + + await personalRpcMethods.ecRecover(requestManager,data, signature); + + expect(requestManagerSendSpy).toHaveBeenCalledWith({ + method: 'personal_ecRecover', + params: [ data, signature], + }); + }); +}); From 962b99fe54ede0d573dff69a7d1667b081ef3fd0 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Fri, 24 May 2024 17:37:58 +0200 Subject: [PATCH 04/25] 6992 getText update and getName fix (#7047) * getText with address as input * reverse resolution support * changelog update * fix * lint fix * name update * updated getname test --- packages/web3-eth-ens/CHANGELOG.md | 11 ++++++++++- packages/web3-eth-ens/src/ens.ts | 11 +++++++---- packages/web3-eth-ens/src/resolver.ts | 13 +++++++++---- packages/web3-eth-ens/test/unit/resolver.test.ts | 7 +++++-- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/web3-eth-ens/CHANGELOG.md b/packages/web3-eth-ens/CHANGELOG.md index c9be2f93561..e5dea285207 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -159,4 +159,13 @@ Documentation: - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- `getText` now supports first param Address +- `getName` has optional second param checkInterfaceSupport + +### Fixed + +- `getName` reverse resolution \ No newline at end of file diff --git a/packages/web3-eth-ens/src/ens.ts b/packages/web3-eth-ens/src/ens.ts index 254a33bc842..8f3e1806127 100644 --- a/packages/web3-eth-ens/src/ens.ts +++ b/packages/web3-eth-ens/src/ens.ts @@ -33,6 +33,7 @@ import { TransactionReceipt, Web3NetAPI, } from 'web3-types'; +import { isAddress } from 'web3-validator'; import { PublicResolverAbi } from './abi/ens/PublicResolver.js'; import { networkIds, registryAddresses } from './config.js'; import { Registry } from './registry.js'; @@ -174,8 +175,10 @@ export class ENS extends Web3Context { * @param key - The key to resolve https://github.com/ethereum/ercs/blob/master/ERCS/erc-634.md#global-keys * @returns - The value content stored in the resolver for the specified key */ - public async getText(ENSName: string, key: string): Promise { - return this._resolver.getText(ENSName, key); + public async getText(ENSNameOrAddr: string | Address, key: string): Promise { + if(isAddress(ENSNameOrAddr)) + return this._resolver.getText(await(this._resolver.getName(ENSNameOrAddr,false)), key); + return this._resolver.getText(ENSNameOrAddr, key); } /** @@ -183,8 +186,8 @@ export class ENS extends Web3Context { * @param ENSName - The node to resolve * @returns - The name */ - public async getName(ENSName: string): Promise { - return this._resolver.getName(ENSName); + public async getName(ENSName: string, checkInterfaceSupport = true): Promise { + return this._resolver.getName(ENSName, checkInterfaceSupport); } /** diff --git a/packages/web3-eth-ens/src/resolver.ts b/packages/web3-eth-ens/src/resolver.ts index c93d150e805..cb345055d95 100644 --- a/packages/web3-eth-ens/src/resolver.ts +++ b/packages/web3-eth-ens/src/resolver.ts @@ -130,12 +130,17 @@ export class Resolver { } public async getName( - address: string + address: string, + checkInterfaceSupport = true ) { - const resolverContract = await this.getResolverContractAdapter(address); - await this.checkInterfaceSupport(resolverContract, methodsInInterface.name); + const reverseName = `${address.toLowerCase().substring(2)}.addr.reverse`; + const resolverContract = await this.getResolverContractAdapter(reverseName); + + if(checkInterfaceSupport) + await this.checkInterfaceSupport(resolverContract, methodsInInterface.name); + return resolverContract.methods - .name(namehash(address)).call() + .name(namehash(reverseName)).call() } } diff --git a/packages/web3-eth-ens/test/unit/resolver.test.ts b/packages/web3-eth-ens/test/unit/resolver.test.ts index f0df74bd2a7..da189e5a45d 100644 --- a/packages/web3-eth-ens/test/unit/resolver.test.ts +++ b/packages/web3-eth-ens/test/unit/resolver.test.ts @@ -239,6 +239,8 @@ describe('resolver', () => { describe('name', () => { it('getName', async () => { + const address = "0x314159265dd8dbb310642f98f50c066173c1259b"; + const supportsInterfaceMock = jest .spyOn(contract.methods, 'supportsInterface') .mockReturnValue({ @@ -255,12 +257,13 @@ describe('resolver', () => { }); }); - await resolver.getName(ENS_NAME); + await resolver.getName(address); expect(supportsInterfaceMock).toHaveBeenCalledWith( interfaceIds[methodsInInterface.name], ); - expect(nameMock).toHaveBeenCalledWith(namehash(ENS_NAME)); + const reverseName = `${address.toLowerCase().substring(2)}.addr.reverse`; + expect(nameMock).toHaveBeenCalledWith(namehash(reverseName)); }) }) From 22c07ad7b00745f1b046e31580a343eca3b59c76 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Mon, 27 May 2024 13:58:55 +0200 Subject: [PATCH 05/25] web3 external provider - Quicknode (#7019) * providers package init * types and quick nodes provider * readme update * import fixes and unit tests * lint fix * lint fix * added host and quicknodes provider info * added host * tests * lint * default provider and itests * package dir rename * web3-rpc-providers * web3-rpc-providers in web3 * packagejson updates * rename test file * tests in web3 package * e2e tests update * lint fix * empty provider * empty provider test fix * lint fix * default provider tests update * lint fix --- packages/web3-rpc-providers/.eslintignore | 1 + packages/web3-rpc-providers/.eslintrc.js | 7 + packages/web3-rpc-providers/.gitignore | 0 packages/web3-rpc-providers/.npmignore | 1 + packages/web3-rpc-providers/.npmrc | 1 + packages/web3-rpc-providers/.prettierignore | 1 + packages/web3-rpc-providers/.prettierrc.json | 1 + packages/web3-rpc-providers/CHANGELOG.md | 38 + packages/web3-rpc-providers/README.md | 58 + .../web3-rpc-providers/assets/logo/web3js.ai | 1516 +++++++++++++++++ .../web3-rpc-providers/assets/logo/web3js.jpg | Bin 0 -> 80258 bytes .../web3-rpc-providers/assets/logo/web3js.svg | 33 + packages/web3-rpc-providers/package.json | 64 + packages/web3-rpc-providers/src/index.ts | 25 + packages/web3-rpc-providers/src/types.ts | 44 + .../web3-rpc-providers/src/web3_provider.ts | 135 ++ .../src/web3_provider_quicknode.ts | 91 + packages/web3-rpc-providers/test/.eslintrc.js | 7 + .../test/config/jest.config.js | 1 + .../web3-rpc-providers/test/config/setup.js | 24 + .../test/integration/jest.config.js | 33 + .../test/integration/setup.js | 24 + .../web3-rpc-providers/test/tsconfig.json | 1 + .../test/unit/constructor.test.ts | 62 + .../test/unit/jest.config.js | 9 + .../test/unit/request.test.ts | 81 + packages/web3-rpc-providers/tsconfig.cjs.json | 1 + packages/web3-rpc-providers/tsconfig.esm.json | 1 + .../web3-rpc-providers/tsconfig.types.json | 1 + packages/web3-rpc-providers/tsdoc.json | 4 + packages/web3/package.json | 3 +- packages/web3/src/web3.ts | 5 +- packages/web3/test/integration/web3.test.ts | 10 +- .../test/integration/web3RPCProviders.test.ts | 61 + packages/web3/test/unit/web3.test.ts | 4 +- templates/.eslintignore.tmpl | 5 +- 36 files changed, 2338 insertions(+), 15 deletions(-) create mode 120000 packages/web3-rpc-providers/.eslintignore create mode 100644 packages/web3-rpc-providers/.eslintrc.js create mode 100644 packages/web3-rpc-providers/.gitignore create mode 120000 packages/web3-rpc-providers/.npmignore create mode 120000 packages/web3-rpc-providers/.npmrc create mode 120000 packages/web3-rpc-providers/.prettierignore create mode 120000 packages/web3-rpc-providers/.prettierrc.json create mode 100644 packages/web3-rpc-providers/CHANGELOG.md create mode 100644 packages/web3-rpc-providers/README.md create mode 100644 packages/web3-rpc-providers/assets/logo/web3js.ai create mode 100644 packages/web3-rpc-providers/assets/logo/web3js.jpg create mode 100644 packages/web3-rpc-providers/assets/logo/web3js.svg create mode 100644 packages/web3-rpc-providers/package.json create mode 100644 packages/web3-rpc-providers/src/index.ts create mode 100644 packages/web3-rpc-providers/src/types.ts create mode 100644 packages/web3-rpc-providers/src/web3_provider.ts create mode 100644 packages/web3-rpc-providers/src/web3_provider_quicknode.ts create mode 100644 packages/web3-rpc-providers/test/.eslintrc.js create mode 120000 packages/web3-rpc-providers/test/config/jest.config.js create mode 100644 packages/web3-rpc-providers/test/config/setup.js create mode 100644 packages/web3-rpc-providers/test/integration/jest.config.js create mode 100644 packages/web3-rpc-providers/test/integration/setup.js create mode 120000 packages/web3-rpc-providers/test/tsconfig.json create mode 100644 packages/web3-rpc-providers/test/unit/constructor.test.ts create mode 100644 packages/web3-rpc-providers/test/unit/jest.config.js create mode 100644 packages/web3-rpc-providers/test/unit/request.test.ts create mode 120000 packages/web3-rpc-providers/tsconfig.cjs.json create mode 120000 packages/web3-rpc-providers/tsconfig.esm.json create mode 120000 packages/web3-rpc-providers/tsconfig.types.json create mode 100644 packages/web3-rpc-providers/tsdoc.json create mode 100644 packages/web3/test/integration/web3RPCProviders.test.ts diff --git a/packages/web3-rpc-providers/.eslintignore b/packages/web3-rpc-providers/.eslintignore new file mode 120000 index 00000000000..94760d2888d --- /dev/null +++ b/packages/web3-rpc-providers/.eslintignore @@ -0,0 +1 @@ +../../templates/.eslintignore.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/.eslintrc.js b/packages/web3-rpc-providers/.eslintrc.js new file mode 100644 index 00000000000..12a507e5126 --- /dev/null +++ b/packages/web3-rpc-providers/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: '../../.eslintrc.js', + parserOptions: { + project: './tsconfig.esm.json', + tsconfigRootDir: __dirname, + }, +}; diff --git a/packages/web3-rpc-providers/.gitignore b/packages/web3-rpc-providers/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/web3-rpc-providers/.npmignore b/packages/web3-rpc-providers/.npmignore new file mode 120000 index 00000000000..8a0be70f3ed --- /dev/null +++ b/packages/web3-rpc-providers/.npmignore @@ -0,0 +1 @@ +../../templates/.npmignore.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/.npmrc b/packages/web3-rpc-providers/.npmrc new file mode 120000 index 00000000000..5cc817c4313 --- /dev/null +++ b/packages/web3-rpc-providers/.npmrc @@ -0,0 +1 @@ +../../templates/.npmrc.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/.prettierignore b/packages/web3-rpc-providers/.prettierignore new file mode 120000 index 00000000000..044e4a3df69 --- /dev/null +++ b/packages/web3-rpc-providers/.prettierignore @@ -0,0 +1 @@ +../../templates/.prettierignore.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/.prettierrc.json b/packages/web3-rpc-providers/.prettierrc.json new file mode 120000 index 00000000000..00ecd510aaf --- /dev/null +++ b/packages/web3-rpc-providers/.prettierrc.json @@ -0,0 +1 @@ +../../templates/.prettierrc.json.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md new file mode 100644 index 00000000000..87f56484e8e --- /dev/null +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -0,0 +1,38 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + +## [Unreleased] diff --git a/packages/web3-rpc-providers/README.md b/packages/web3-rpc-providers/README.md new file mode 100644 index 00000000000..59284dbb29b --- /dev/null +++ b/packages/web3-rpc-providers/README.md @@ -0,0 +1,58 @@ +

+ web3.js +

+ +# web3.js - Web3 Providers + +![ES Version](https://img.shields.io/badge/ES-2020-yellow) +![Node Version](https://img.shields.io/badge/node-14.x-green) +[![NPM Package][npm-image]][npm-url] +[![Downloads][downloads-image]][npm-url] + +This is a sub-package of [web3.js][repo]. + + +## Installation + +You can install the package either using [NPM](https://www.npmjs.com/package/web3-rpc-providers) or using [Yarn](https://yarnpkg.com/package/web3-rpc-providers) + +### Using NPM + +```bash +npm install web3-rpc-providers +``` + +### Using Yarn + +```bash +yarn add web3-rpc-providers +``` + +## Getting Started + +- :writing_hand: If you have questions [submit an issue](https://github.com/ChainSafe/web3.js/issues/new) or join us on [Discord](https://discord.gg/yjyvFRP) + ![Discord](https://img.shields.io/discord/593655374469660673.svg?label=Discord&logo=discord) + +## Prerequisites + +- :gear: [NodeJS](https://nodejs.org/) (LTS/Fermium) +- :toolbox: [Yarn](https://yarnpkg.com/)/[Lerna](https://lerna.js.org/) + +## Package.json Scripts + +| Script | Description | +| ---------------- | -------------------------------------------------- | +| clean | Uses `rimraf` to remove `dist/` | +| build | Uses `tsc` to build package and dependent packages | +| lint | Uses `eslint` to lint package | +| lint:fix | Uses `eslint` to check and fix any warnings | +| format | Uses `prettier` to format the code | +| test | Uses `jest` to run unit tests | +| test:integration | Uses `jest` to run tests under `/test/integration` | +| test:unit | Uses `jest` to run tests under `/test/unit` | + +[docs]: https://docs.web3js.org/ +[repo]: https://github.com/web3/web3.js/tree/4.x/tools/web3-rpc-providers +[npm-image]: https://img.shields.io/github/package-json/v/web3/web3.js/4.x?filename=tools%2Fweb3-rpc-providers%2Fpackage.json +[npm-url]: https://npmjs.org/package/web3-rpc-providers +[downloads-image]: https://img.shields.io/npm/dm/web3-rpc-providers?label=npm%20downloads diff --git a/packages/web3-rpc-providers/assets/logo/web3js.ai b/packages/web3-rpc-providers/assets/logo/web3js.ai new file mode 100644 index 00000000000..669ef50e7cd --- /dev/null +++ b/packages/web3-rpc-providers/assets/logo/web3js.ai @@ -0,0 +1,1516 @@ +%PDF-1.5 %âãÏÓ +1 0 obj <>/OCGs[5 0 R 6 0 R 29 0 R 30 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + Print + + + + + 2017-01-27T15:51:37Z + 2017-01-27T15:51:37Z + 2017-01-27T14:51:33Z + Adobe Illustrator CS6 (Macintosh) + + + + 256 + 240 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgA8AEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A7F+an5hy6Ov6F0qTjqMq VubhTvCjDYL4Ow3r2Hz2IQ8x8teevMXl+cvaXBlgdi01pMS8Tk7k0rUMfFTXCr2Xyl+Z/l/X+FvI 31DUWoPqszCjn/iuTYN8tj7YKSzDArsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdir5W1nUptU1a71CYkvdSvKa9gx2H0DbJIQeKtqrMwVQWZjRVG5JPYY q+ify70jzPpujKmvXrTu4BgtX+NoFp9lpDuT/k9BgKWV4FdirsVdirsVdirsVdirsVdirsVdirsV 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 + + + + + + uuid:394c157d-8cf0-f94e-8261-98ccb840e1bc + xmp.did:106820F817276811822ACF3CAA06C913 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + uuid:1898a391-1dba-4249-9e7f-8804d46504b0 + xmp.did:FE7F11740720681183D1839CF7E6F44E + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:FE7F11740720681183D1839CF7E6F44E + 2017-01-06T15:27:37Z + Adobe Illustrator CS6 (Macintosh) + / + + + saved + xmp.iid:106820F817276811822ACF3CAA06C913 + 2017-01-27T14:51:33Z + Adobe Illustrator CS6 (Macintosh) + / + + + + + + Document + Print + + + False + False + 1 + + 3840.000000 + 2160.000000 + Pixels + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + CMYK Red + RGB + PROCESS + 237 + 28 + 36 + + + CMYK Yellow + RGB + PROCESS + 255 + 242 + 0 + + + CMYK Green + RGB + PROCESS + 0 + 166 + 81 + + + CMYK Cyan + RGB + PROCESS + 0 + 174 + 239 + + + CMYK Blue + RGB + PROCESS + 46 + 49 + 146 + + + CMYK Magenta + RGB + PROCESS + 236 + 0 + 140 + + + C=15 M=100 Y=90 K=10 + RGB + PROCESS + 190 + 30 + 45 + + + C=0 M=90 Y=85 K=0 + RGB + PROCESS + 239 + 65 + 54 + + + C=0 M=80 Y=95 K=0 + RGB + PROCESS + 241 + 90 + 41 + + + C=0 M=50 Y=100 K=0 + RGB + PROCESS + 247 + 148 + 30 + + + C=0 M=35 Y=85 K=0 + RGB + PROCESS + 251 + 176 + 64 + + + C=5 M=0 Y=90 K=0 + RGB + PROCESS + 249 + 237 + 50 + + + C=20 M=0 Y=100 K=0 + RGB + PROCESS + 215 + 223 + 35 + + + C=50 M=0 Y=100 K=0 + RGB + PROCESS + 141 + 198 + 63 + + + C=75 M=0 Y=100 K=0 + RGB + PROCESS + 57 + 181 + 74 + + + C=85 M=10 Y=100 K=10 + RGB + PROCESS + 0 + 148 + 68 + + + C=90 M=30 Y=95 K=30 + RGB + PROCESS + 0 + 104 + 56 + + + C=75 M=0 Y=75 K=0 + RGB + PROCESS + 43 + 182 + 115 + + + C=80 M=10 Y=45 K=0 + RGB + PROCESS + 0 + 167 + 157 + + + C=70 M=15 Y=0 K=0 + RGB + PROCESS + 39 + 170 + 225 + + + C=85 M=50 Y=0 K=0 + RGB + PROCESS + 28 + 117 + 188 + + + C=100 M=95 Y=5 K=0 + RGB + PROCESS + 43 + 57 + 144 + + + C=100 M=100 Y=25 K=25 + RGB + PROCESS + 38 + 34 + 98 + + + C=75 M=100 Y=0 K=0 + RGB + PROCESS + 102 + 45 + 145 + + + C=50 M=100 Y=0 K=0 + RGB + PROCESS + 146 + 39 + 143 + + + C=35 M=100 Y=35 K=10 + RGB + PROCESS + 158 + 31 + 99 + + + C=10 M=100 Y=50 K=0 + RGB + PROCESS + 218 + 28 + 92 + + + C=0 M=95 Y=20 K=0 + RGB + PROCESS + 238 + 42 + 123 + + + C=25 M=25 Y=40 K=0 + RGB + PROCESS + 194 + 181 + 155 + + + C=40 M=45 Y=50 K=5 + RGB + PROCESS + 155 + 133 + 121 + + + C=50 M=50 Y=60 K=25 + RGB + PROCESS + 114 + 102 + 88 + + + C=55 M=60 Y=65 K=40 + RGB + PROCESS + 89 + 74 + 66 + + + C=25 M=40 Y=65 K=0 + RGB + PROCESS + 196 + 154 + 108 + + + C=30 M=50 Y=75 K=10 + RGB + PROCESS + 169 + 124 + 80 + + + C=35 M=60 Y=80 K=25 + RGB + PROCESS + 139 + 94 + 60 + + + C=40 M=65 Y=90 K=35 + RGB + PROCESS + 117 + 76 + 41 + + + C=40 M=70 Y=100 K=50 + RGB + PROCESS + 96 + 57 + 19 + + + C=50 M=70 Y=80 K=70 + RGB + PROCESS + 60 + 36 + 21 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 65 + 64 + 66 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 113 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 130 + 133 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 147 + 149 + 152 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 167 + 169 + 172 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 188 + 190 + 192 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 209 + 211 + 212 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 242 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 237 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 242 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 222 + 23 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 33 + 64 + 154 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 152 + + + + + + + + + Adobe PDF library 10.01 + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 8 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/Thumb 36 0 R/TrimBox[0.0 0.0 3840.0 2160.0]/Type/Page>> endobj 32 0 obj <>stream +H‰lVIŽ9 ¼ç+øTK"©åêcNÆÀðÁ(Ìrhð4P@ýÞA*•ªên(EJ\‚A*Ÿþz¦§/Ï‘>ýñLÛ¯-RN%7‰´ûßÿÿÞ¾ÓÏíéù[¤Ë+ÅÐEñ”ØðLÌD¯¼þ¯ÿ}Ý~Q¢ˆ_¢,RC­•)iÖ¹%ºüØìåm×RÊ=¨VÚ{uS¡,—YHz¨¥ÑeÛ“” ©QÍ!¶†5nJ½…œ±Î9ãPÊ5ä"v„[ ­u²Wˆ…vU…7Åê•nÛŽø,FÄô²í¥”PŠÒ^$$5DDp”ÉdÈ4Ú‹»Û™90ëÜqÝö|˜dDZÛÚÍß a1439°<±¾0}Àf0{ê–h¹E#þ£‡R 5Y9$§ +ïzòXÁ]@~ì3Ï‹¹̬Î3L„>󨳂¦é|c¨Î²s%®’sZNÓVþëöÏöu‹Ac†„pœ‡Ž–~R©ñcé˜b^A°Ð¹><\×I£ /wP‹¡;žbJ@|‰—n[×Á…°fDÚˆ…^î Ð-[D@DňÞ( TIf—´öйkèÎÙ‘UE†'Gx"/ÛÞ!ÈQ„LwBq¨:÷¨pë¨.RÐZ¬[ÀY¤¦h»À=jØò€°{9äÜ—ü€ ºÎþà¡A×ÕCÇIüYøÊ8w;vuu-Ó¹ö2/;@†ØÒræ ¢fdöŒk6zŒ1ãàFM¹¶˜Ç¯ãk׊xì¹ð]*C1Õyl ÚDTA­ÚœªÖu&4íÇ`‚pv)Ý5b•Ǹ+¦ µ·†+VEC04Õ,žúTp9ãÜÔp©Œª)½ÕôíÜ1RÒÙ«9¦¢ŽÖ¿mÿ½XÑ­xúh¯Êïš±ñPxÊkÉeõ㨫Ô&Ú‰ŒAeLÆ9Jl1|ÞÝ)Y•|z—f*Ñ·í.G·%:×oÚ]Ž®Õ~¶»Ljêœhí(×Õîò®Ýeê—MBCÓúÎõ#û£\fßch³\™æÚÏij\m–«Ìrµ#¹JÜ¢ßoï¹;oÙŽ?ÅæüIÝ <¨çh];¡è5%Ñ5ÁŠ_–)f:£á¯k WÅ5Mq\ê×ùà»[À3Ñ’° ů +4äšx_× NÌÊFÓŒ•§W]³·¦²…}r€ŠbÖ™xò‹2AÈ'9ÓÛõ §¯´Ö5ØÇ'Äm +y°ùpoòÔfZm§4ó$1úG€ðó|m=o¯4¾½úºý`öuÚÐ endstream endobj 36 0 obj <>stream +8;Z]!gMI$9&4O4Loo+g]Y:Y;L9GQ$:@3.,T.n*;fRief@%Sif_3dV)Ok+/'6SR3bl +9q7Fhkme7N\oK:^?"i4k6BkiO2r#nub+]#^#o2T&%;/3"U%t=#DK/;5(hd<.rJl^nXukH^04p_5&"H=J0K1J +F,$ endstream endobj 37 0 obj [/Indexed/DeviceRGB 255 38 0 R] endobj 38 0 obj <>stream +8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 +b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` +E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 29 0 obj <> endobj 30 0 obj <> endobj 41 0 obj [/View/Design] endobj 42 0 obj <>>> endobj 39 0 obj [/View/Design] endobj 40 0 obj <>>> endobj 35 0 obj <> endobj 34 0 obj [/ICCBased 43 0 R] endobj 43 0 obj <>stream +H‰œ–yTSwÇoÉž•°Ãc [€°5la‘QIBHØADED„ª•2ÖmtFOE.®c­Ö}êÒõ0êè8´׎8GNg¦Óïï÷9÷wïïÝß½÷ó '¥ªµÕ0 Ö ÏJŒÅb¤  + 2y­.-;!à’ÆK°ZÜ ü‹ž^i½"LÊÀ0ðÿ‰-×é @8(”µrœ;q®ª7èLöœy¥•&†Qëñq¶4±jž½ç|æ9ÚÄ +V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚óÈtÕ;\ú” Ó¥$ÕºF½ZUnÀÜå˜(4TŒ%)ë«”ƒ0C&¯”阤Z£“i˜¿óœ8¦Úbx‘ƒE¡ÁÁBÑ;…ú¯›¿P¦ÞÎӓ̹žAü om?çW= +€x¯Íú·¶Ò-Œ¯Àòæ[›Ëû0ñ¾¾øÎ}ø¦y)7ta¾¾õõõ>j¥ÜÇTÐ7úŸ¿@ï¼ÏÇtÜ›ò`qÊ2™±Ê€™ê&¯®ª6ê±ZL®Ä„?â_øóyxg)Ë”z¥ÈçL­UáíÖ*ÔuµSkÿSeØO4?׸¸c¯¯Ø°.òò· åÒR´ ßÞô-•’2ð5ßáÞüÜÏ ú÷Sá>Ó£V­š‹“då`r£¾n~ÏôY &à+`œ;ÂA4ˆÉ 䀰ÈA9Ð=¨- t°lÃ`;»Á~pŒƒÁ ðGp| ®[`Lƒ‡`<¯ "A ˆ YA+äùCb(ЇR¡,¨*T2B-Ð +¨ꇆ¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r 9‹\A&‘GÈ ”ˆrQ ¢áhš‹ÊÑ´íE‡Ñ]èaô4zBgÐ×Á–àE#H ‹*B=¡‹0HØIøˆp†p0MxJ$ùD1„˜D, V›‰½Ä­ÄÄãÄKÄ»ÄY‰dEò"EÒI2’ÔEÚBÚGúŒt™4MzN¦‘Èþär!YKî ’÷?%_&ß#¿¢°(®”0J:EAi¤ôQÆ(Ç()Ó”WT6U@ æP+¨íÔ!ê~êêmêæD ¥eÒÔ´å´!ÚïhŸÓ¦h/èº']B/¢éëèÒÓ¿¢?a0nŒhF!ÃÀXÇØÍ8ÅøšñÜŒkæc&5S˜µ™˜6»lö˜Iaº2c˜K™MÌAæ!æEæ#…寒°d¬VÖë(ëk–Íe‹Øél »—½‡}Ž}ŸCâ¸qâ9 +N'çÎ)Î].ÂuæJ¸rî +î÷ wšGä xR^¯‡÷[ÞoÆœchžgÞ`>bþ‰ù$á»ñ¥ü*~ÿ ÿ:ÿ¥…EŒ…ÒbÅ~‹ËÏ,m,£-•–Ý–,¯Y¾´Â¬â­*­6X[ݱF­=­3­ë­·YŸ±~dó ·‘ÛtÛ´¹i ÛzÚfÙ6Û~`{ÁvÖÎÞ.ÑNg·Åî”Ý#{¾}´}…ý€ý§ö¸‘j‡‡ÏþŠ™c1X6„Æfm“Ž;'_9 œr:œ8Ýq¦:‹ËœœO:ϸ8¸¤¹´¸ìu¹éJq»–»nv=ëúÌMà–ï¶ÊmÜí¾ÀR 4 ö +n»3Ü£ÜkÜGݯz=Ä•[=¾ô„=ƒ<Ë=GTB(É/ÙSòƒ,]6*›-•–¾W:#—È7Ë*¢ŠÊe¿ò^YDYÙ}U„j£êAyTù`ù#µD=¬þ¶"©b{ųÊôÊ+¬Ê¯: !kJ4Gµm¥ötµ}uCõ%—®K7YV³©fFŸ¢ßY Õ.©=bàá?SŒîƕƩºÈº‘ºçõyõ‡Ø Ú† žkï5%4ý¦m–7Ÿlqlio™Z³lG+ÔZÚz²Í¹­³mzyâò]íÔöÊö?uøuôw|¿"űN»ÎåwW&®ÜÛe֥ﺱ*|ÕöÕèjõê‰5k¶¬yÝ­èþ¢Ç¯g°ç‡^yïkEk‡Öþ¸®lÝD_pß¶õÄõÚõ×7DmØÕÏîoê¿»1mãál {àûMśΠnßLÝlÜ<9”úO¤[þ˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ +¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäü儿 æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿ ÷„óû endstream endobj 33 0 obj <> endobj 44 0 obj <> endobj 45 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 16.0 %%AI8_CreatorVersion: 16.0.0 %%For: (Ian Meikle) () %%Title: (Web3_70.ai) %%CreationDate: 27/01/2017 15:51 %%Canvassize: 16383 %%BoundingBox: 1170 -1782 2670 -378 %%HiResBoundingBox: 1170 -1781.6396 2670 -378.3604 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 12.0 %AI12_BuildNumber: 682 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: 0 -2160 3840 0 %AI3_TemplateBox: 1920.5 -1080.5 1920.5 -1080.5 %AI3_TileBox: 1517 -1359.5 2300 -800.5 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 6 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 2 %AI9_OpenToView: -1717.0015 636.9985 0.3333 2078 1150 18 0 0 32 191 0 0 0 1 1 0 1 1 0 1 %AI5_OpenViewLayers: 77 %%PageOrigin:1614 -1476 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 46 0 obj <>stream +%%BoundingBox: 1170 -1782 2670 -378 %%HiResBoundingBox: 1170 -1781.6396 2670 -378.3604 %AI7_Thumbnail: 128 120 8 %%BeginData: 14636 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FFFFFFA87D7DFD7CFFA8FD0452A8FD79FFA87D527D527D527DA8FD %77FF7D525352525253525259FD76FF527D527D527D527D527D52A8AFFD72 %FF7D52527D5252527D52525259527DA8FD71FF7D527D527D527D527D527D %527DA8FD72FF52535252525352525253527DA8FD39FFCACAA1C3A0C2A0C2 %A0C3A1CACAFD2DFF7D527D527D527D527D527DA8FD37FFC3C3BBBBBABBB4 %BBB4BBBABB92BBBBBBC2C9CAFD2AFF527D5252527DFD04527DFD35FFA1C2 %98BA92BB92BB92BB98BB92BB98BB92BB92BA92BB99CAFD28FF7D527D527D %527D527D52FD33FFCAC9BBBA92BBBBBB98BBBBBB98BBBBBB98BBBBBB98BB %BBBB98BBB4C2C9FD26FF5252525352525253527DFD0CFFA87D7DFD23FFA0 %BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB92BA99 %CAFD24FF7D527D527D527D52537DFD0BFFA87D525352A8FD1FFFCABBBBBA %BBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBA %C9FD23FF5252527D5252527D52A8FD0AFFA852527D5252527DA8FD1BFFCA %C292BB98BB92BB98BB92BB98BB92BB98BB92BB92BB92BB98BB92BB98BB92 %BB98BB92BB92C2CAFD21FF7D527D527D527D5253A8FD0AFF7D527D527D52 %7D52537DFD19FFC2BBB4BB98BBBBBB98BBBBBB98BBBBBB98BBB4BB92BBB4 %BA92BBBBBB98BBBBBB98BBBBBB98BBB4BBCAFD20FF525352525253525252 %A8FD09FFA8525352525253FD05527DA8FD14FFC998BA92BB92BB92BB92BB %92BB92BB92BB92BA99C3C3CAA7C9A0BB92BB92BB92BB92BB92BB92BB92BB %92BBA8FD1FFF7D527D527D527D5259A8FD09FF7D7D527D527D527D527D52 %7D527DFD12FFC9C2B4BBBABBBBBBBABBBBBBBABBBBBBBABBB4C2C9FD08FF %C9BBBBBABBBBBBBABBBBBBBABBBBBBB4C2FD1FFF527D5252527D525252A8 %FD09FF7D527D5252527D5252527D527DA8FD10FFCF9ABA92BB98BB92BB98 %BB92BB98BB92BB92BA98C9FD0BFFCF99BB92BB98BB92BB98BB92BB98BB92 %C3CAFD1DFF7D527D527D527D52527DFD09FF527D527D527D527D527D527D %FD11FFC398BBBABB98BBBBBB98BBBBBB98BBBBBB92BBC2FD0EFFC9B4BB98 %BBBBBB98BBBBBB98BBBBBB92BBBBC2C3CFFD19FF525252535252525352A8 %FD08FFA85952525253525252535252A8FD0FFFA1BB92BB92BB92BB92BB92 %BB92BB92BB92BB92C2A8FD0FFFA1BA92BB92BB92BB92BB92BB92BB92BB92 %BB92BA92C2C3FD17FF7D527D527D527D52527EFD09FF527D527D527D527D %52537DFD0EFFCABBBBBABBBABBBBBBBABBBBBBBABBBBBBBABBBBCAFD10FF %CFC2BABBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBABBBBC9FD15FF52 %52527D5252527D52A8FD08FFA87D5252527D5252525952FD0DFFA8C2B4BA %92BB98BB92BB98BB92BB98BB92BB92BBA0FD11FFCABB92BB98BB92BB98BB %92BB98BB92BB98BB92BB98BB92BB98BB92BBC3FD13FF7D527D527D527D52 %53A8FD09FF527D527D527D527D527DFD0CFFA87D75BBBABB98BBBBBB98BB %BBBB98BBBBBB92C3CFFD11FFC2BBBABB98BBBBBB98BBBBBB98BBBBBB98BB %BBBB98BBBBBB98BBBBBB92BBBBCAFD11FF525352525253525252A8FD08FF %A85252535252525352527DFD0BFF7D525253527698BA92BB92BB92BB92BB %92BA99CAFD11FFC999BA92BB92BB92BB92BB92BB92BB92BB92BB92BB92BB %92BB92BB92BB92BB92BB92C2CAFD0FFF7D527D527D527D5259A8FD09FF52 %7D527D527D527D52A8FD0AFFA87D527D527D537D99BBBABBBABBBBBB92C1 %C9FD11FFCAC2B4BBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABBBBBBBABB %BBBBBABBBBBBBABBBBBB92C2CAFD0EFF527D5252527D525252A8FD08FFA8 %53527D5252527D52527DFD0AFF7D527D5252527D52535299B4BB92BA98C3 %CAFD11FFC2BA92BB98BB92BB98BB92BB98BB92BB92BA92BB92BB92BA92BB %92BB98BB92BB98BB92BB98BB92BBCAFD0DFF7D527D527D527D52527DFD09 %FF527D527D527D527D52A8FD09FFA8527D527D527D527D5259527C99BBC2 %FD12FFC998BBBABB98BBBBBB98BBBBBB98BBBBBB92BBBBC9C9CFCACAC2C1 %B4BB98BBBBBB98BBBBBB98BBBBBB92BBCAFD0CFF525252535252525352A8 %FD08FFA85952525253FD04527DFD09FF59FD0452535252525352522E7DA8 %FD11FFA1BB92BB92BB92BB92BB92BB92BB92BB92BB92C2A7FD07FFCAC998 %BA92BB92BB92BB92BB92BB92BB92C1FD0CFF7D527D527D527D52527EFD09 %FF527D527D527D527D52A8FD09FF7D527D527D527D527D527D527DFD11FF %CFBBBBBABBBABBBBBBBABBBBBBBABBBBBBBABBBBCAFD0BFFCFFD04BBBABB %BBBBBABBBBBBBABBB4C9FD0BFF5252527D5252527D52A8FD08FFA87D5252 %527DFD04527DFD09FF52595252527D5252527D527DFD10FFCAC292BA92BB %98BB92BB98BB92BB98BB92BB92BBA0FD0EFFC992BB98BB92BB98BB92BB98 %BB92BB99FD0BFF7D527D527D527D5253A8FD09FF527D527D527D527D52A8 %FD08FFA87D527D527D527D527D527DFD10FFC3BB92BBBBBB98BBBBBB98BB %BBBB98BBBBBB92C2CAFD0FFFC3BB98BBBBBB98BBBBBB98BBBBBB92C2FD0B %FF525352525253525252A8FD08FFA85252535252525352527DFD09FF5252 %52535252525352527DFD0EFFCA99BA92BB92BB92BB92BB92BB92BB92BB92 %BA99CAFD10FFA8BB92BB92BB92BB92BB92BB92BB92BA99FD0BFF7D527D52 %7D527D5259A8FD09FF527D527D527D527D52A8FD09FF7D527D527D527D52 %7D52FD0DFFCFC292BBBBBBBABBBBBBBABBBBBBBABBBBBB92BBC9FD11FFCA %C1BABBBABBBBBBBABBBBBBBABBBBBB92C9FD0BFF527D5252527D525252A8 %FD08FFA853527D5252527D52527DFD09FF5252527D5252527D527DFD0EFF %C2BB92BB98BB92BB98BB92BB98BB92BA92C3CAFD11FFC2BB92BB98BB92BB %98BB92BB98BB92BB92BBCAFD0BFF7D527D527D527D52527DFD09FF527D52 %7D527D527D52A8FD08FFA87D527D527D527D52537EFD10FFC398BBBABB98 %BBBBBB98BBBABBBCFD12FFC998BBBABB98BBBBBB98BBBBBB98BBBBBB92BB %CAFD0CFF525252535252525352A8FD08FFA85952525253FD04527DFD09FF %FD055253525252A8FD11FFCA99BA92BB92BB92BA92BBC9FD11FFA1BB92BB %92BB92BB92BB92BB92BB92BB92BB92BBA8FD0DFF7D527D527D527D52527E %FD09FF527D527D527D527D52A8FD08FFA87D527D527D527D5259A8FD13FF %C9C292FD04BBC9FD11FFCFBCBBBABBBABBBBBBBABBBBBBBABBBBBBBABBBB %CAFD0FFF5252527D5252527D52A8FD08FFA87D5252527DFD04527DFD09FF %52595252527D525252A8FD15FFC992BBC2FD11FFCAC392BA92BB98BB92BB %98BB92BB98BB92BB92BBA0FD11FF7D527D527D527D5253A8FD09FF527D52 %7D527D527D52A8FD08FFA87D527D527D527D52527DFD17FFCAFD11FFC3BB %92BBBBBB98BBBBBB98BBBBBB98BBBBBB92C2CAFD12FF7DFD045253525252 %A8FD08FFA85252535252525352527DFD09FF525252535252525352A8FD27 %FFCA99BA92BB92BB92BB92BB92BB92BB92BB92BA99CAFD14FFA8527D527D %527D5259A8FD09FF527D527D527D527D52A8FD09FF7D527D527D527D5252 %7EFD25FFCAC2B4BBBBBBBABBBBBBBABBBBBBBABBBBBBB4BBC3FD16FFA853 %5252527D525252A8FD08FFA853527D5252527D52527DFD09FF5252527D52 %52527D52A8FD24FFA0BB92BB92BB98BB92BB98BB92BB98BB92BB92C2CAFD %18FF527D527D527D52527DFD09FF527D527D527D527D52A8FD08FFA87D52 %7D527D527D5253A8FD22FFCABBBA92BBBBBB98BBBBBB98BBBBBB98BBBABB %BBCFFD1AFF7D525352525253527DA8FD07FFA85952525253FD04527DFD09 %FFFD055253525252A8FD20FFA8BB92BB92BB92BB92BB92BB92BB92BB92BB %92BBC9FD1CFFA87D527D527D527D52FD09FF527D527D527D527D52A8FD08 %FFA87D527D527D527D5259A8FD1FFFA8A8A1C2BABBBABBBBBBBABBBBBBBA %FD04BBC9FD1FFF52535252527D52527DFD07FFA87D5252527DFD04527DFD %09FF52595252527D525252A8FD1EFFA8A87DA87DA199BA92BB98BB92BB98 %BB92BBC2FD21FF7E527D527D527D5252A8FD07FF527D527D527D527D52A8 %FD08FFA87D527D527D527D52527DFD1DFFA8A87DA87EA87EA8A0BBB4BBBB %BB98BBB4C2CAFD22FFA8525253525252535252A8FD05FFA8525253525252 %5352527DFD09FF525252535252525352A8FD08FFA8A8A8FD11FFA8A87DA8 %7DA87DA87DA87DA092BB92BA99C9FD25FF7D7D527D527D527D527DA8FD04 %FFA8527D527D527D527D52A8FD09FF7D527D527D527D52527EFD09FF7EA8 %7EFD11FF7DA87DA884A87DA884A884A799BBC2FD27FFA852595252527DFD %04527DA8A8A85252527D5252527D52527DFD09FF5252527D5252527D52A8 %FD08FFA8A87DA87DA8A8FD0DFF7DA87DA87DA87DA87DA87DA87DA8CAFD29 %FF7E527D527D527D527D5259527D527D527D527D527D527D52A8FD08FFA8 %7D527D527D527D5253A8FD09FF7DA87EA87DA8A8FD0CFFA87DA87EA87DA8 %7EA87DA87DA8FD2BFFA853525352525253525252535252525352525253FD %04527DFD09FFFD055253525252A8FD08FFA8A87DA87DA87DA87DA8A8FD09 %FF7DA87DA87DA87DA87DA87DA8FD2DFFA87D527D527D527D527D527D527D %527D527D527D527D52A8FD08FFA87D527D527D527D5259A8FD09FF7DA884 %A87DA884A87DFD0AFFA87DA884A87DA884A87DA8FD2FFF7DFD04527D5252 %527D5252527D5252527DFD04527DFD09FF52595252527D525252A8FD08FF %A8A87DA87DA87DA87D84A8FD09FF7DA87DA87DA87DA87D84A8FD30FF7D53 %527D527D527D527D527D527D527D527D527D527DFD08FFA87D527D527D52 %7D52527DFD09FF7EA87DA87EA87DA87DFD09FFA8A87DA87DA87EA87DA8A8 %FD32FFFD055253525252535252525352525253525252A8FD08FF52525253 %5252525352A8FD08FFA8A87DA87DA87DA87DA8A8FD09FF7DA87DA87DA87D %A87DA8FD33FF7D52527D527D527D527D527D527D527D527D527D7DFD08FF %7D527D527D527D52527EFD09FF7EA87DA884A87DA87DFD09FFA8A87EA87D %A884A87DA8A8FD34FF7D52527D5252527D5252527D5252527DFD0452A8FD %07FF5252527D5252527D52A8FD08FFA8A87DA87DA87DA87DA8A8FD09FF7D %A87DA87DA87DA87DFD36FFA859527D527D527D527D527D527D527D527D52 %7DA8FD05FFA87D527D527D527D5253A8FD0BFF7DA87DA87EA87DFD0AFFA8 %7DA87EA87DA87EA8A8FD0DFFFD05A8A9A8FD22FFA87DFD05525352525253 %5252525352525259A8FD04FF7D525352525253525252A8FD0CFFA87E7DA8 %7D7EA8FD09FF7DA87DA87DA87DA87DA9FD0CFF7DA87D847DA87D847DA8A8 %FD21FFA85953527D527D527D527D527D527D527D52597DFFFFA8527D527D %527D527D5259A8FD0DFFA8A87DA87DFD0AFFA87DA884A87DA884A8A8FD0B %FF7DA884A87DA884A87DA87DA8A8FD22FFA87DFD0552595252527D525252 %7D5252527D5252527D5252527D525252A8FD10FF7D7DA8FD09FF7DA87DA8 %7DA87DA87DFD0BFF7E847DA87DA87DA87DA87DA87D7E7DFD24FFFD05A87D %527D527D527D527D527D527D527D527D527D527D52527DFD11FFA8FD09FF %A8A87DA87DA87EA87DA8A8FD09FFA8A87EA87DA87EA87DA87EA87DA87EA8 %7DA8A8FD26FF84FD0452535252525352525253525252535252525352A8FD %1CFF7DA87DA87DA87DA87DFD0AFFA87DA87DA87DA87DA87DA87DA87DA87D %A87DA8A8FD26FF7D52527D527D527D527D527D527D527D527D527D5259A8 %FD1BFFA8A87EA87DA884A87DA8A8FD09FFA8A884A87DA884A87DA884A87D %A884A87DA87EA87DFD26FF7D52527D5252527D5252527D5252527D525252 %5952A8FD1CFF7DA87DA87DA87DA87DFD0AFFA87DA87DA87DA87DA87DA87D %A87DA87DA87DA87DA87DA8A8FD24FF7D52527D527D527D527D527D527D52 %7D527D527DFD1DFFA87DA87EA87DA87EA8A8FD09FF7EA87DA87EA87DA87E %A87DA87EA87DA87EA87DA87EA87DA8A8FD24FF7D52525352525253525252 %5352525253525253FD1DFF7DA87DA87DA87DA87DA9FD08FFA8A87DA87DA8 %7DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8A8FD22FF7D7D527D %527D527D527D527D527D527D52A8FD0AFFA8FD12FFA87DA884A87DA884A8 %A8FD09FF7EA87DA884A87DA884A87DA884A87DA884A87DA884A87DA884A8 %7DA8A8FD22FF7D535252527D5252527D5252527D5253A8FD09FFA8847EFD %11FF7DA87DA87DA87DA87DFD09FFA8A87DA87DA87DA87DA87DA87DA87DA8 %7DA87DA87DA87DA87DA87DA87DA87DFD22FFA87D5253527D527D527D527D %5252A8FD0BFF84A87DAFFD0EFFA8A87DA87DA87EA87DA8A8FD09FF7DA87E %A87DA87EA87DA8A8FFA8A87DA87DA87EA87DA87EA87DA87EA87DA87DA8A8 %FD21FFA8525252535252525352527DFD0CFFA87DA87DA8A8FD0DFF7DA87D %A87DA87DA87DFD09FFA8A87DA87DA87DA87D847DFFFFFFA8A87D7E7DA87D %A87DA87DA87DA87DA87DA87DA8FD23FFA87D52595259527D7DFD0DFFA8A8 %7DA87DA8A8FD0BFFA8A87EA87DA884A87DA8A8FD09FF84A884A87DA884A8 %7DFD07FFA8A87DA87DA884A87DA884A87DA884A87DFD26FFA8A87DA8A8FD %0EFFA87DA87DA87D847DA8FD0AFF7DA87DA87DA87DA87DFD0AFFA87DA87D %A87DA87D84A8FD07FFA8A87DA87DA87DA87DA87DA87DA87DA8FD39FFA8A8 %7DA87DA87EA87DFD0AFFA87DA87EA87DA87EA8A8FD09FFA8A87DA87EA87D %A87DFD0BFFA8A87DA87EA87DA87EA87DA87EFD3AFF7DA87DA87DA87D7EA8 %FD09FF7DA87DA87DA87DA87DA9FD0AFF7DA87DA87DA87DA8A8FD0BFFA8A8 %7DA87DA87DA87DA87DA8FD3AFFA87DA87DA884A87DA8FD09FFA87DA884A8 %7DA884A8A8FD0AFFA87DA884A87DA87DA8FD0DFFA87DA87DA884A87DA884 %FD3AFFA8A87DA87DA87DA87DFD09FF7DA87DA87DA87DA87DFD0BFFA8847D %A87DA87DA87DFD0FFF7E847DA87DA87DA8FD3BFF7DA87EA87DA87EA8A8FD %07FFA8A87DA87DA87EA87DA8A8FD0BFF7DA87DA87EA87DA8A8FD0FFFA8A8 %7DA87EA87DFD3BFFA87DA87DA87DA87D7EA8FD07FF7DA87DA87DA87DA87D %FD0CFFA87DA87DA87DA87DA8A8FD10FFA87DA87DA8FD3BFFA8A87EA87DA8 %84A87DA8FD06FFA8A884A87DA884A87DA8A8FD0BFFA8A87DA884A87DA87D %A8A9FD11FFA8A87DFD3CFF7DA87DA87DA87DA87DA8A8FD04FFA87DA87DA8 %7DA87DA87DFD0DFF7E847DA87DA87DA87DA8A8FD11FFA8A8FD3DFF7DA87E %A87DA87EA87DA8A8FFA8FF7DA87DA87EA87DA87EA8A8FD0DFF7DA87DA87E %A87DA87DA8A8FD4FFFA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8 %7DA87DA9FD0DFFA87DA87DA87DA87DA87D7E7DA8FD4EFFA87DA87DA884A8 %7DA884A87DA884A87DA884A87DA884A8A8FD0EFFA87DA884A87DA884A87D %A87DA8A8FD4CFFA8A87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87D %FD0FFFA8A87DA87DA87DA87DA87DA87D7E7DFD4CFFA8A87EA87DA87EA87D %A87EA87DA87EA87DA87EA87DA8A8FD0FFFA8A87DA87EA87DA87EA87DA87E %A87DA8FD4BFF7DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DFD11FF %A87D7DA87DA87DA87DA87DA87DA87DA8A8FD4AFFA8A87DA884A87DA884A8 %7DA884A87DA884A87DA8FD12FFA8A87EA87DA884A87DA884A87DA87EA8A8 %FD4AFFA87E7DA87DA87DA87DA87DA87DA87DA87D84A8FD13FFA8A87DA87D %A87DA87DA87DA87DA87D7E7DFD4AFFA8A87DA87EA87DA87EA87DA87EA87D %A87DFD15FFA8A87DA87DA87EA87DA87EA87DA87EA8A8FD4AFFA8A87DA87D %A87DA87DA87DA87DA87DA8FD16FFA8A87DA87DA87DA87DA87DA87DA87D7D %7EFD4BFFA87DA87DA884A87DA884A87DA8A8FD18FFA87DA884A87DA884A8 %7DA884A87DA8A8FD4CFF7E847DA87DA87DA87D7EA8FD1AFFA87DA87DA87D %A87DA87DA87DA87DA8FD4DFFA8A87DA87DA87DA8A8FD1DFFA8A87DA87DA8 %7EA87DA87EA87DA8FD4FFFA8FFA8FFA8FD1FFFA8A87DA87DA87DA87DA87D %A87DFD62FFA8FD13FF7DA884A87DA884A87DA8A8FD60FFA8847DA8A8FD11 %FF7DA87DA87DA87DA87DA8FD61FF7DA87DA8A8FD11FF7DA87EA87DA87EA8 %7DFD60FFA8A87DA87DA87DA8FD0FFFA87DA87DA87DA87D7E84FD60FF7EA8 %7DA884A87DA8FD0EFFA8A87EA87DA884A87DA8FD5FFFA8A87DA87DA87DA8 %7DA8A8FD0DFF7DA87DA87DA87DA87DFD60FF7DA87EA87DA87EA87DA87DA9 %FD0BFFA87DA87EA87DA87EA8A8FD5EFFA8A87DA87DA87DA87DA87DA87DA8 %A8FD09FFA87D7DA87DA87DA87DA8FD5FFF7DA884A87DA884A87DA884A87D %A8A8FD09FF7DA884A87DA884A8A8FD5EFFA8A87DA87DA87DA87DA87DA87D %A87DA87DA8A8FD05FFA8847DA87DA87DA87DA8FD5FFF7DA87DA87EA87DA8 %7EA87DA87EA87DA87DA8A8FFFFFFA8A87DA87DA87EA87DA884FD60FF7E7E %7DA87DA87DA87DA87DA87DA87DA87D7E7DA8A8A87DA87DA87DA87DA87DA8 %FD61FFA8A87DA87DA884A87DA884A87DA884A87DA87DA87DA884A87DA884 %A87DA884FD63FFA87D847DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8 %7DA87DA87DA8FD65FFA8A87DA87EA87DA87EA87DA87EA87DA87EA87DA87E %A87DA87EA87DFD66FFA8A87DA87DA87DA87DA87DA87DA87DA87DA87DA87D %A87DA87DA8FD69FFA8A87DA884A87DA884A87DA884A87DA884A87DA884A8 %84FD6AFFA8A87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8FD6CFFA8 %7DA87EA87DA87EA87DA87EA87DA87EA87DA8A8FD6EFF7DA87DA87DA87DA8 %7DA87DA87DA87DA87DFD70FFA8A87DA884A87DA884A87DA884A87DA9FD72 %FFA87DA87DA87DA87DA87DA87DA8A8FD74FFA8A87DA87DA87DA87DA8FD77 %FFA8FFA8A87DA8A8A8FFFFFFFF %%EndData endstream endobj 47 0 obj <>stream +%AI12_CompressedDataxœì½yÉu'ú ò;Ü÷‡i`–2cÉEo0ÀÝÊ£ÛÔ²-c0hPìR‹c6Ù`³åÑûôïüÎyóVY¥7²\ 4»˜•ËY~gû›ÿëW_½Úóáww¯âM¿ëþæoŽï^úðñç;¾ºûÅ»w?þðé#.ýä×?Ý ãMO7í1­7þóÝÇÞ~xÿsþÿòOÿä¯ßïþáîí¿½»ûéî'?¥Ë¿yûéÝýâ_î~¿žú›×oj¯£çO¯?Ñ/Ãô³~øYè‡i7äŸç7¼~ÿÇ×?üðöÿ½Ã+âéÚáÃï¿yûþÛÇÿM‡©ß½¦9ìˆã4Ó=ÿýí¯ï~ؾq¸ã2–»oâØ'zäôáÍßݽÿô«ÞÜýðÃñûøùîø'|Êëoé7¯wÿz÷î݇ßÞ½~óoÍCþúöí»;úäï^Ú °ÿž>üøöÝ7ÿøãw¿»£Éç€ËñkîòŸ~ ¾¨[üŒËÓ׿øŽ®|u÷é •^ˆIüõßêaÐEn?ù¿¾ûö-/MÚÿü©vûñÃ÷ß½þøoxv÷* c¿‹sêw½üú7wß}ÿŽæWfa ýM¦yègü¿ý§ÞO_$÷fZˆWCÌ ÝbOϽßV¦ëîoïþýç»üðþNædÿñÓW²b)ÑSü·üæ×?¾»ûøOïß~¢±Ž¸´È¤üÇoîÞÑýþüí»×<܆ò·Üð›×¿½ûD+üáÝŸxûÍöšô¿ý§;¬\üòû»÷¿ùðÏ„¡ü-oB¿èÕ^7M´p¿¢¥üåÇ·ß¾}ÿóa½0M£,óß}|ûMYå)ìfù‹_q3Wÿ-öŸ|ÍŧOwïuzhwÿ¡Ú-ýÍ?|E/>¿ÿæøá;,È8"´MÞÓz÷á[ùÿÌ¿¡Çü^¾‚ÿý5­Ý¯>¾}>»äßÌ_ÿêÝô«¿ûøáÇïñþ÷ºŸIøç»7tîiy¿Ùýòwÿ‹þAœwðî7_¿¡èß~óïzowôqïvòKz’ÿiÿøéÓÝïéì•ÇåêùýïÞ}ø¾êÖ¯¼~ÿÍî_^üþá®õîõû×w|Ý{þû·¤ß¼¦™*}—kè”vÊ÷49üß²zÁ=7T¿zÄ‹^ú‘©»÷ßüà}Ë?Û˵‡ûûê öàÇÝáã?üa÷›Þy·í¯¼w½ÌWqÿ_Æ;~żÿå{™ Ë7é ë7Iú‹{ Ý}ý ôË¿äޯ߽{ûíÇ×ßÿáí›­lüÞß$¿ûœõ§ï~÷áÝÛ¾+û©ºò«×?½}óîî«?ýðéî»G/îîüÍ["rWŽñ½÷|õï¯?½ùÃß¿ýÝÇ×ßÞÝ{ú°¿ûþÚû_ýøöÓ]™ ß}ñf÷Õ^ÇŸñé·|çWÞaþšHMÜ_½º‡ê‡~wx_ýþï>¾þæ-1’Ún_CŽÚ}õoúiWÿƒXWؾéþG×ßLË4Íý—œ§Üõh7C"Ák¤H˜~=áÿC—vóõácõäΞ–«OîìÉ=Ioìw㌚„ ê„Øß×Oëäð׌bž2ï‚Fp8ù’ÙÌo/Æ/?¾~ÿíÝߪ0J ²º@ÝeY”ÿÚõ¹j£¶r%5¿¯ïÛºF­ã¿þõ|8N‡óáöØÃ1Ó1Çãtœûãáx<žŽçãí©? §pJ§|OÓi>-§Ãéx:ΧÛs¨…s<§s>Ýy:ÏÜ3Ý9ÑýÖ2·¤?¥U‹m}Gêø/ôÜ?óî{>ŸªvÜh‡¶ßh‹´ŽÿBÏãÓTó!ïó’gÚicÎ9åI|M·éLß{L‡´OKšÓ”Æ”SJ1…4¤¾‹·ñÌ=Çãf;<²í×­ã¿þ›lšî¨-q«¶fÛpýsª¶¨ÿÌ£žÓ<ÎӼ̇ù4Ÿ—~–¸¤%/ã2/ËrXŽËi¹Ý÷4–´Ïûi?ï÷ûÃþH“{{膞ãa:̇åp8·¶Ütµa —F#¨~3—ÿyv:½ÚBÕ†¦õ¥o›VÿÑÍÊ.ý|;ŸiôGšÕ=ÍíL3<Ιæ:Îaæ~ºÎô]‡iO4nžˆ€MyJSœ)Týx;žiÞŽãaÜË(Ç8Þ6í|µmœamÍÆlvVà«VöØz¯Åæª=Uz ÿwUgënéoùž)δÃ4–3u6ÐJt°&:b{:lG:v·tCŽtG:” ÏÓ[:´o¢c<Ñôìi¢Nãm7õ4w‘fq¤ù\hf4÷sOóMú»¬öéöxÑNÜìÿòÓñöp»¿]nçÛév¼ÍÜï’×ýDäf!úJDv:DoSÞž?=>]^xÛöòÖÓêÍo{oKÕfoSÕFiI†Uï þRb#±D ŽÃ±§W‰Áéˆîé Ît`ÇC¦£é‡žpÞŸèXï÷ ñi?ÒaOtèÃ~Ø÷ËmGôóD´à°ì‰*ÌËDô!ˆK Š!g©?ö§þÜßý0 aˆÄ¨iIoŸ†™TÿýpŽÃ‰¸Ô-m‘!„C +9Ðb†)Ìa ûpÇp +çpK»dèbˆ1¦˜ãH›ÛeÑ s¢m~Ûl`"\ýÌmÒfܹý×%ÏÎ iÔÖUÿØ¢³©ÙÔm [­Û¾|qÛŠÐÑTò»3>oé÷ýæ™fšçyàyN4Ë3Ïògó|Ëó܇ÐñTGšj™ì™§{¦éÞó”cÒÑÎܘÆA[Жª–;Z’ºMÛMXÁ|ÚÓy8“|‚î–‘O 1âÏåç žg!«Jl%ÆØÓØÛ²ÛyóK›ø?iå¼”3´¯ÚaÕª³Øm’ƒ‹fgùúŸó—´îâÒ•÷?¶u¼M™˜]¯¬ìÄrd&b^N×ѵÀ²eÏO‚¾ …;ÐÊî+¶=v•P †CG™ÖáÄÛ•gWVûÄMþ´íµ-U›;’ë6m7á'¡"‘‹LÛ4Ò¶Åîii(GÞê{¢38ˆD»œføg y8vtˆD´öt¨>\Ä^蘡¬áÐÉ! ÜäO/­H ÞN]jÚq»²]® /û9%h=sìI0cMhH`âJ7Ñø!L)WšP£Ò=C_¬Ùa¢†zWsd”•èxÆ3D²Æ ¿"¶R +oR?Í / 1ÓµÒÝ<ßÚVî{•qØ+Š´â‘{ŒË(ñ‚çÐ'iÄøÃ§>/¥«q¼™s\ª>O26KŒßÒ!æ„–>†QúZÂÀ>Í=1XÌÀª¯0ßðÊ•±=O2¶H²– è)Ïèl7Ô_ˆcEŸ/‡¹ÖØ?ÿÑÏÑÔ¿úñ{7~ÿILF»~ûíû»OŸîHi¿þ;zWtP¥Ÿˆ,Ð#­dJø!AðîpÆ!-ø|lûÎæ?ä´kÖSù,”±ì¬›u³³nvÚMY/ëÆà–‘nË.O7PH+àäÙ»HçiÝÞŒy)Sïq¸™Ç>î¦åfš†çøõ7<Ëø—¼”=c§Ÿsþéýû×ßÝ}³ûV/í:i9“ÁW¬@/€f º´ƒA5„[ÆQNª'@Sس¶}tÑc¡åÕQ  BÈs{V% L@˜X¥€Rµ")Äå‚Ô (¬_œ:füüJ<»È¨P8 rPcvOÏöôÌ‘n¯3i"kÝGzáLÚv‚¦M²!´ì…4ÂÌÚuOâ'ôê…TG`@ñŸS>t4²™ôÌDíÀ Ï‘á€=@©s a@¾ˆ,YœYª€Di"BŠ ùá¡¡#i!³t0°pÄg²~’Y}ŽA<ˆT@¢*ü'V\¹}DV^ aÍï\Xq°¿÷¬DÈß™ý}dÎþ¶ÿŽ]õOûû¬ŸYV'GäthÚñžv -–v¶Ö•½Ý^o[z7–Û:ùßE u¨øÂÌÃ1†3)à ™†™¡†ƒ g…‡93°6Ï mÈmËSG»ó–¶Ð`l{EÙÎŒ³ ´³km[o;)â6(æ–c§°ÛÀ›ÃÇC ºŒçðdàƒ‹§3æ‰öÂH7G&gí¬gâ´ËĤƒºíšžYJß³ü~dšajª{–üƒCÈÙ‘À™Q?ЊÃ× `wÀ°ÅîÅŒeÉÎEc¬5~Vf•ýYÝ£‰kŽÓå? \’Õúδ{XÆÒ;«+PNöBlfZŒH‡úV:ôX®Ï¯¼…$h"°Îð{€Ueì%éŠ×+Ù +úyD-Xt¢#Ëâ% $¸ Kn$–³X×/s_ ¼Ë|C¿ ?zjGÂ)gÆÁÂÆHT3¨åB ™igSV‰·Äó†—yj@êéøá.RÒzfŸ$ÏA‚afñŸ?‡lÃV—›‘j£ÒsvË#%>“XuL ™›z"Ù;K—=KÜÄá€o޶£¼dËðõ\>Mžè7о‘(×C›YM^\YžZý³65ÍhoQªs§—RÓbÕÂê_Ò¢jàÁ›þéZżVÎWªº©ë…»­\˜%·Žÿ·” ÌUK››6UM8rù¯²®H3%®±FCÙƒJÕG AÂÏFŸ¶ì,$ALº%2|`ó  ( 4‰‰"ðbÁHqf D(*`ªQ +ÂT˜†,Œ‘íGf• zbòšÕÎy…{†ð@Òakƒµ ö¶‰ím°¸Áæ;’¿À‚æçg5¾Y˜€<Lpb„KŒHž$±Š˜Ém¯hÐÜ192P (İÐI›C ã¢㤉:†…†^; CŒ³ +8494d[•7_µŸŽ*bí}ƒLB+Øl‹;è2º} +¿XÏ 8gäŒ nb.2îÖ/ c6IkÃò~G#‡˜_ f#€ÈïÜÅàFÿûä?ˆ¼Ýñ>Ú»‰ S^ \G6p‰yËŒ[Å´%¦ØÄۣ硂¸Xay?¸öÄÁl°™—Ÿ-°¼ì0nÉ’cµþ€Ü1öw¬¿‚úõŠ÷ Ô·ð*f]E¦¼‚FtíäÀ&•âC³^åjþùóØØ_:ìu½ ?WH-ƒÝ¥…ªµ¦ÖV-á ÜÉÿXf-mªÚÜ´¥j­ç‚z5túCíüpjZý§±$ÔŒ­Ø³;þ_mîn-Ë+}ªjcÓÜ,Ù5ö—ÖÓZaÖv˜+f˜0šï?â®™GeÕ® _ÍÌ¿öÌÍ ”œxfoUÕ‚²%êVbô(„YØw 5Uÿ:óˆ{–hëa¢‰eÆ.&Æ2ÕÈl¯8ñb±]WÜ»ÇhîQÜUµ>vóWlÜ¿ö+0wÿj ¬']EYÁÔñòñÒñªyÅ{z‘{œŸÝªqì–©âIÿ>±©ùÄ⡊ÄÙꊠP„ŒZÄ8o‰"Õ¶Ñ-;©9R,î²1VÞôáÍ—†ÿkÖüûÌóÍ©KlðWàÆRå ž˜^Óp .pßv}c’6k[ª¶¯Ú¡iǪ©ô[¯»:˜R6©ò¶¨šwàÿŠ‹´3ïŠ[w8À¾‘©ò³ƒ“#秆όŸ˜Ú©LŽJ}Pô˜È>¸d3æ$cÿÆ.86û¤å#fvWçZ»\ûÖ/ªuôN·–GØbî6s³šÝj^ÙÍ×fs™»m—±ãÊiìŠËXíä(û¤Ýû+m¹ÒæÒܪŠç©œ€× Ôýw‰ÑqY¦>°ýtšFÆA¬¬=÷Ǭf” [5P‘Áo’Úà Le‘|Þ~y¬tJ2÷9ÅÈ=-KÛuˆj²Çò̆é2­J¼˜zÖ^eN§1DÜ•3ma|ÍÌãøö&¼ŒØ\Ù¨m¶õz Ó&.õ\> —J›¸T‚¡×q)•ñ>¹I "“úOíÙÔqÚðV+¾j+oµ®qX›”âšÃZrŠ˜“ÜkÍ„wXàéٙǤ‘{jÉç¬ 1OÀMD Ah,ŸBoièÄ +È-ËD"F`3°›‘±™™™ØÏÑ›³Ÿ3ã9ìPÙ+TXxŠÌ“À•2s¦‘¹ÓÄjf.µ0§²v`ž%è\ÇPRQ…*ÏÆy›Íú]³”Õ4»ØÆŠ³i¡×¶ Šã>iò‚ÌÍþßì8^‹ò™…ìTÙÉ&¼mŒ`‚(2v0( 9(L‰Ý‘öjȧ G“#¥‚¡²òÒ©*j”\ÊÖ4òj×ipqõ–e HZ‰•û‰é.Nü dœˆ:H|Ò˜½‰ÙÂ9Æ-óúˆNýã˜?*îl^^öÿ½µŽ~õäWŸÄ¬ö[ßZºß¯~*ïYòPç³ÖŽ^$›E¥!“‰ä§"hÕ>{Ó©ìÖiDã³ØŒj;Ñ„ùËKøèèטC÷˜X5¿nG_Ô±{è +³^ˆv¸0ÀΕ ªSÏúÕ©2ÀNj}…À?Ø—³Ø¶%¸OÔmÑMìÛäÖ]nEl¡­ˆl&°™/…Éi£Kh$›uâ©Pvv)ì ’–¹VŒ¬Z§â`ÁýVWQÖ+¹ïF¡pŽ$ΕØS >›¢ÏUáçØ]Ê?WÅŸµèS >EèéÔ¥øÔˆ;µ 37îÅc#ÅDÉmui}»Úuî¿vjµZ“¹õª±_Õ¬Ô5-šlî*4ùá0²õ¹«ˆJ{1Í—ò±¸ãר)úfüÌð¸qÞÈ;ea |Ï»û›ö9ö;û`c~bÇ\Øl™§S»8O^xòñß‘ùóÆþ;óšÝ‚gË–òò?!´Ùõ`‰I4¯ªÀHGfFIÛÖ_³Ù´7±yÛjas ¼-*ìÇ~¾Im*üfñÜûe®"ΖÚ1¹ò[~ŽÞx\Ë0ÌåM&JÂÈ81V¾èYdò…kïp³à²Ó íÀÊ:óœÊ(és9ÎrÊ©çÈËDÒ;ôqáHäH¿‘8º¶×&éY{}š™fÜ4ÓŒpŽ•™f`àVX ³f о ‚ØmÁ„72¯8@[c>‘º*ƒ“K¢’?BëaÊJöˆâ RÛÛ9}DÑÇFw6Í9¹CˆéÍÇ{â8ˆswî —Zó¡ +Áï Tù‰ƒÈ¾»|aþAæ¥Pû),•—B ÄðP uT¨ü↠8÷y«Þ6ÝܺÆËm¹ÈÛs¼Ç¹íÒÅþt[Þn+·û[ß…¤Â®ñ‡ûòæ^tÝÊ©îÉí¯°Ã"É+íÈ2ÉA3\Üj~ ‘%'–£ÄäuˇX«ÄYξ,ÿDFwÌöêˆшµ“Ù¡u/sï2‘!©uL1LŠÌUÖ1š‚v ÚDfΣÚAÅòyVãf`"Â^‹»,Xq¥ývX|ÊjOÁµ¯ y šßX›¤Ð<ƒ9‰uê†SÇ[Ìê9h±Å&Z''<©áÁÍŸlúì˧Ù=›gåæUÌWÝ{gkñ4›çà.—fZ,^P +áuEÅ.ŽdûúÏRµ¹j­×ßh­Óòªm¹ËäÕQ­ëUëª ¶ çÔuëê,·OoÝÆÅóSZ÷´ÇÿStX,S½¶[•gÉqÈYªI®5£$®$~7qÂCOÚ2ËØÏ; =ÙÈØö<Ý~褚Ѹâ.¹%«½hwÝLÓ*šf}ùiÆ–yÓØ2¿ÄļÄļÄļÄļÄļÄļÄļÄļÄļÄļÄļÄļÄļÄÄ<åψ_bb^bbþSÇÄìݽr ³Ž‡ÉMF·¹ +{a°®IÑw¾}òŸûê(}a‡Îö[†Qª¶ÃmNœ‰jP†Ž€}4s¨Í¢)þÎd3°]Ò¬~Óaéš`šS<#u<Þë¤~{fò`ö‡æ?³;õ‡8Îúfÿñ&T°ÿl 6†uÃßz_Çηì0aûYŒ½üT"yÆ*’ç 8`©/–‹Ù—l†Rã#cËØ^˜"MX²¿ƒxi{«ždw¾‡óÌÖö¥°rK0ûÒ*ykWf “¹ŒšS뱊æ“ô­ŠUÅaY Vìt%²_Mº*³‡\•ÊGIåëUÿÄKEkþqUè8v*y¼”Îl×yTxSÚv{–ªÐ&ÌYwáÏQ3Õ!MÅ+'¯J²ÏîÅ5žëह2Wÿ2Ý¥_Ç!•ºÊÓ·òø5_àÏ ºÔ„¸îªÀ ´Æ­- hh kËœaQ@œ;£kÜ8Z'Žk 46ßš÷Æu·ÃköMxM ®±ðš6¸¦ ­bÓU5uXM•AÀ‹6Öá4ë’¥`ã£òLn$È«½[ÝÔÎÖ©imq“YÎØhð¸ð”û‚SV¡)˜»î"0¥ JY…¤´á(mŠêÝ*ü¤ ;IM¬IcÒF•xI×Ä´‘!MxǶKM#G^ûýÓiZIþ©==ko¿èêß6øöìÎ GNÆyo7\;¤îA®ÝT€nš÷U°rª|,LŽXÚ@u—'dd>º®bauÜúIC€Í­RF:­yR£w^Õ®óÿ•d‚uä4´ +{hi½ÅŠT¼í¹8@CÿOS÷yô¿MDzÅCªWBU»•-u+TÕâ iTÑük•m8e¡ø<ºî +Å/A”MåóÑ’sf=bȉ„DP€›[Ò?HêmÖj[Ègx€¥+Ôäúz= ›ô$@Ö4ðfëi”pÆÉš W2isd†D°%Þ“mùŠ ÝŠ{‹K,;ð%ÏcÇN­5L%â}Æ)—W%~§E'µ ÃYì¸b9¹ìèÂlX®øÀAžX¦ÄU¡gÜ4 < ¢á(«8Ah…Œu­îgêNpï*ÏÃȬ‰I÷Yº2(…ÿ>1O)—¾Æp³KßÚ“úSŒfšÂÀRXΜhŽ´cÛW681¬héEùîgêOǶðLDÇÓ¡#ŸÙCªòʨû6ãu\œ`ö߬Ûý<ý=‰wl‚§ù%AÑK‚¢—E/ Š^½$(zIPô’ è%AÑK‚¢—E/ Š^½$(zÊŸÿ¾$(zIPô’ è%AÑK‚¢—E/ Š^½$(zIPô’ èš7To¦4ŒÏä[e½½¤(ú‹JQ”7=ÖòÐÄX”¼7¶óµVSç®±·¸ÕÅÿ”*†ÉÛÚàbÆfÏXYØØ¸W›ÿA‘Æ“šYYI]Úëø_ö褣Å:¶‚€g•Zöj–<6Q¿Zbx Ì÷à¦ÈÛFjÉêý^üßk¯ ÷›èÔ xá_áX‚42>ºMiþÐ#ëÈÁRhÊR)í«<Ì雨3×A1ÔUfºz³Ô[$³Hdc1»›í†N-œÜm›¡Þ©qV¼kTÄK¤UÛ g)l.y‚o³OÏú —H]=o„ÀœÂ„Ø\|³$Û1s©ƒ!, ¢„C˜ {T 4m +YÏçøSÅNhKˆ¦ª•„—föôY²ö0Кqvß,ymœ½*ákÔkö×Ìz…¬2x[æ=ËÁææsÐÕŽyöµtmËAWþ$xiKœR…$³Ç¬êQ}nÕçÀÖ4²$ ’õÂòÁžâgp» +pÕ$k]ûRÙžù^pîÿL‡×u·V•`y¿XÁ'*@në(ƒóB§Aà§ó£Ûõ?•U¤Û0lÛ>JõÔ _†})úÕ5Øc °Ck±8ö¥¸W·Qµ±¯lË¥Zã¾IÓd&æ´Æ*» +s\i ®3”˜˜Zkp½¡sKòZo¸Ã…dy=ׯ­ëíQ+ÝmÀ¶W÷QkÛUÀæãWöè+»¯¢hx]»{ªqöá4‡{¢iÔy «@èsB_BÐî;àð³9 ò,>Ëê+PBž¶4‹•åõl œ÷·ÍJÙkch÷ Etk¬×½Ž´©–ûa;¬Ö¸]a^ßn½ÀWV·]Û­3«'¶»ð i×u߬k*ñkç•Wµ«Ôü­@¶+zþ*?Ü÷¡W¥H´:ñ1‰n8Ï™kûúá iO–o3ÀèÙºds@ÆÑÌ'‰ssß‹ª:[þYuë¹VY§xÓÇ8Õn§ÏÑÙÓ´ÉͰeºúÚäƒÚãJu ݆æøÞX¹æ]*]£5>Zg¼®2škX%Ž*ÊÂa¥53kQ½;¶”¯õƱÑU ¼ÔŸ{U;Ï.VëŽî÷UÚ¡’´äbŸˆÇè˜Ò+ku²«´ÉÙµÉåB›¼Ð%]•\y|v•.ùš¤«Šd·¡I&×%-§\­K®=( +®À;¤SX¡Ñ&]ó?Šìqõ¢Oîk7gS(;Þ,Eû° ûF§¼¢1ù¦Q¼áË5ÏòS+™]¥cŽ®cN¾iäÿ¦+˜ÇÊÿ—vAçægé—Œhoª—]­_²íEV¼†š(\à•· Ö:§Ô±†9±•fñ•>ëJ¼Ò¶Î²Ê£¯òáÂú5Ø*'EF‡“du¥Ýü%«l.ëS•’¬¬òÿ)å쯺Ãû솵îÙ&XpëawEûlõϪ!±¶!#íñ1ZêƒZéZeé6´–‡ôÑ{U–®ÑY­‹^WYºGê,E]§ ^¹”Æ{c\÷wØÞü˜®¾ {à±Ïn×:|x„ŸÙácÛ#ÄÄ'þyé𑹞3xÅ¡‘ÝéëLzƒ'’Ÿ6rè™cÞl:c·J:4jÓ X‚ñ .{É 6Ä!»C8$aòâ%«žé…¬V¹ÂK¦pÉ>vž¼Î~ðX‹*Ò™¡¤6Ñ·¥ö¶?UònûSãê ¹¤uªÚ¹n:ÚY˜Þe´scë-^iÙZW~¬Úøèvñ§»¼ôè?HSüä ÃÏ’¦ø/±Ãrf%ÁÈ&YœVù +¬’z]¡u›å#©N³æ3KG0vzúM^yæã&yú/í ‡© hGFÍÄX³…ñÚȪX6Ö¡eM5%KÜ^R¶ßjºv -³ísÇùž÷îŒ^§cž€Ý]Ò9ôÞó¬—üêžQ½«2¨×YÒE“ÝQ}ÒKO¾×úKÒŠ~vîDt·z#ìzn-zKM«Šœ¦U›»‹œáÛA×¢ë¸Ân3Øðø†úUkÑ“ÇÛ‡¯¶Ï12ÿê°D½ÛŸóF»öôñJ;tMå¶íhËVë6.^TNz°UÙ;ºúŸÕÆíÖ]ûÅ—¶kæ/mÝ—?úÒá_T‡u–Â:OÅçÉm3%ne¨°|‰uŽŠ´òKX¡·Ý†+Q©úVÕ|«üNÄCÁžUÉ·®©øV×|³Â[E=®•ó8 bò¡ŠohŸQÆ£óz—¥^×Å<¶ +z\öè.k|l”Œ»Þ.Ê~tWª<¦mV ¹^§î Û_i‡vfqb:­ù霞èÔ,t>3ÍÎå‰óJÊÁÈÁg\èàáЮ¼wæC¶ Ê(ŽUä|·\‚¯M¦ÜàQàЭtÔê—Õ5Æû!PA-¡¾e5v« «6Äê´bÕYqÑW³âøîA3!ÝzÀÕYåV•zµ÷ú:³aY –4.˜5*+ylVô|›Á³n–VEž]d_äT…m;m¶+%‘8$©iÝ•$(û/m]óÏ Zõ¹­{ŽNþò:,¨~¯màöÙ¥@G?r~Ú—Ôæ)†¼¬$ZÛ`Ð=â»6 ÏÓÝᇎëìЕ!"Œ©' +a/ÙøÝ3fúÅ8ÜÀdÓÍ8äÔ<·}GûüD½æ0îÃ6ž_ßáÏOÓ*ËãúòÓ +qÓ¢›ÄáEÒì‘"°4EÜM¿º4<: 6?­Røeà‚ßRîåVs–4©Ä^“ŠŒšZ"©@ÀúH}Æ8~V­´çèù@¾%çB$L]+ÕyJͼRàzÐ:y ™ª,@û +ž1hÆPI>µ…<<²…˶² .ó0‰ë8õkïô}¢y€/i©›ÑŒk«$´tÚ&„\ëá³t'1¬iéGÍ8»„$/n¶0SÂêǯ…†žÚÑçðùÃÛOw»;¼{ýæßèd7ÿ¼¨^µµX¶²¯–>°@lÔð1‡E³@XÆÕÑkÛ–Ú=måž’Xõ6]³6jÜb]ݶ P;\x^•®ŠU4ÓíhEó9=oúœzÙùîj™ËËB—÷”ºt ðÐi†9Å7]<¯Ê_V0[/¹º¢ÂºžÂ:«î=+Û©ÿª-níµUWzXWh›|ºU…¦Î—yôx¶u}&O°qµ>SE»]k +ùˆuï*WãÖÙøréKÓíµçuï6kœ®—~_¯øã×òЯklÙJ¶õ:t-e%ëÕÚ*©É/jmuiUlëµ,ž¢î'Z1º ½©;nbLÕæg>¢£û¯V¶‰?Ž×¯½VÁ¶^Ẏmò2Ó“r¬uW-vYî³›IìÀŠÍÄ}üí$«ýX2ÊT¦³mù¨"2­ÙúXñ‹¬æ±²„œÕm9kF™ƒf” lÖŒ2l‹þ°Ð£XdÇbÏ(;XÇF0ÀH]àôK‡åć6qº¥ÑÛ[M¯Öápª1ÈϯÖr‰„aéY+vu.ž—ˆ¶'ÕìêækMÖþ€Ìh×=O>Ng MºÇ¥µ«³Ú=m-ÿZk¯}~^ÂîYV±JJÓ=~ -3á’µ\¯f÷ÈSùèÕìžéLújvŸs"e5×:áD +ëi9Èc‚²) 2HEdú! yä+\+ùŠSésõÍð U¢®êqtáëüðþWß¾ÿôöý·¯^Uê]ý‹î¿Ço¢üæW¯?}ºûøžô¾ÛïÞ¾þöŽT>ûi7¤ñ&“Ô´†ù†öÄ./ñfX¦¸‹Ó|C²XæÁîùïßþ;ýïGþqÐñÿöOüÏÿ‡~ü_tñßéûwÿ°ûÿ³ß}#ü`”½ÄúÜ}GW/Þ´ûûúª èïë6/6Ï¿§ÿ~¶ÿøéôöͧ·Þ¿þø§ÝÏûÙáÇw»Ÿì¡óñõù›·Ÿ>|üú@Z/ÍÙ׿yûîîë_ß½ùôÓÝßÒÿ7ýç_ûKÞóhñ2 $ä +lè(qÖ)¯Â½ÐÎÀæ!½•vËî·¯ñU©›H¿æé†ö½L@DZ(ú¨9ÜÀ ±#‰æ¦'™t7L‰~¾Bö¼Æt3†¸;òs“Ò2¶'bc»´Ì(CeoþJ -íºBS³è`rˆluú¸aÄ}´F¨15Œ }Æ<Ñ•…–û|Dm(Z<™–pÉá†1£t^¢ûh{Ç~á¾è~ý§I®ðÑ’'é×™–Žz§µ¡½HÌí& Š6ú¢]ŠQô2A ¯{2Ñq æ«iètÎqnº2ÜDß'Œï2­‚žpbÊ73Šlaf¦’:BW¶E1ÐöòçW䕘Zˇ$Ñ >ÍØœS@_£Œ5bx>Ö‘ˆP¤q$:ý4Z:AP£4É»~ÇäõÒ>óOw¯8 ßLƒ#–ëÉ$ ‘'&òjØ‘3Â:ƒw´@盤 +úõá[êûUˆ´þDD^ÑGMèDÐ2н¯2S•€h!";d¥½E<â·Ø£¯âH»å¸fzÉ)ØoøÊu´]#úŽ<¢t¦¦ÞÍJÑ3Ôõ+Z yÊÓí´ð~:h$[íŸõ~úaŽ$y$î‚–¦å÷ÿžYÐá°ÍØ~Vÿ{÷³üð‰x؇ßÐJü­­®NñÏ~}÷úÝ?¼þôñíÿ¦›w?9îa"Ço~ÿáãwò+åˆÄ<¿ù𻻯÷¿X¾¦|õéOÄ1Ëë¾ á·ßØöOØö7ï‡q÷“Ÿî~û/ôÓù‘?òÄ¿Ãc ƒ‰¢ج}Yƒæšh(¶.QÉ<ѯIÆ#@BÃÆNÿéœ`yw“²NlnZ:¯DBéÀÇžÆ4‚x€*ÓcaJi7ұͨ¾IrË8á ~Úq\zŒŽåLćþ?/ç×3CD®ÄY9‹‘ú# èœxÑ­”ŸÏ$q:¥ÄÜh“-[tt;1ˆ ;Œš¤e7š_zjšnæøít_bLƒ¥1µ¤:7ج»4ÐTÑ<™â§‰lDÒ&äU´3™·ƒ …Œn"¾Åûž¨)"4tP~ðØL±UyޱÌíÂ7‘XC§“Fª'˜-Ïñ_.Ô'o£±qçKæ¡RÂ^iDÑhSQ€æi¦¤O%‹=¯ì4â—Ô”(Ñû˜Fê'@†ÃfX„ûðct$3„¨e²Ç&ƒ¦hÌ,?Dmñú¸¨0óL`e Ÿ8ñõz7‰¾”v!¿b ¾ð0?®ƒƒ. 3 +ó¦éœP”Ý’ýO#[¹ÝïšåS±O",Ùvaê…ÉËcvQ„7Z’Áèqÿ7½+â»–›‰¨O>~Rùe¤m@«O› ÒÒË…ÜvÆîiõÃLÌCîS‚DJûœ¼<’BнØ!ÒIŒ2³™„='$ÅëØ0.$ζOÜl¤ç4èBÇüL;Ž8n¢í ‰!CÔ‡Å,kCÛ)|6©sÄy‰ÜcÊ”;LxjFÙU*ŽŸz‘Ìùýô[âº4UØB´ƒ™¨o\zZ'îšÖ¥q‘Vwáƒ8 ‘X.Dœšñ€ãK2*)·£Ó˜4‹LAgP¤Iº0¼ÚJEpÔv}ŠŽ SÌ‘Ø s/3 Âó R5FÐËhÆCo¤‚Pšð”qO/sG{}†b…ï"­œ„áY$9¾D#{.ÍŠr’HóŸvËCÒÎ +ÓɈµÈ"R`Ç"ï/#sçô8O+ÍÙÄô¨õ³$4SN²E‚Ï6 KùD´0?=Þ…—Ç,½,¶ÇéœçJL}hÒùÆþX¸±ïå"9>õyøBI"s?ÏljMÐé!ФN£È‹Íf”†ÝËâ™ Ÿ &ô¢¨’ }‡%¢ ÞÐ/0yñDâÐÔ…ÇÚg]Œ£êÁÄNø+¼…ºe { Ã/@ñ¾Ã#³‹òöLo t½\»îõ%ƒðÿ=1>Ýú¼ý³~‡_´‘dHÖ#Qqj†’jÜ~þÿš¶9†PfÊk`uÂfŽÄ:Ýž:¹Ò2.èÜ£æõòðS=mB[D|f€âkËL¤EFÜlöÚe[†Äý.ÝS™–dÄ˪—q´i¾=Y]ˆŽØ†æÅg¢ÞæP:™¾ÛQÈ $ðé±ÃBj‘š~iŽSkŠ~-·£‰Ž{“úgb/Щ씓x#ºƒ’ ÝjLE*21¬ºÑÈ®ÌdŒâ ×)䱡K™6ûSrê0 'Nîô z'ÑÙ©!‚¸+o3J™Á¡‚)Åw±RÜ 0ÐŒ,g,ŒpC_Nà_FÝe'ajÊ2ÉËYHùĹïD”q¬ôœ±­”ßÈÛ§±aJXÇ™vŸq®L¿Y¹VÖ†-ÜLZ +Ì#tvž±É !ôË©_¨Ù­_4¦ as3¶ÂâXÍÛ1„z®æcÜøg%CØ54°;é|Eð´îF`Á‹¦9WwÑïö˜à“!mã´4òqq’ Ç"F0á2)+cU0­µ,†A±èn¦c¦aºLÇ0 Ó˜ZôÃØ3ôYãàkM‚¤ÅUÆWəăn³»4Š»z8ª¸Šmż£j³Š&úƒ#Eb0Ù8ìe:¸µC/]›˜ …?Õq€âq=Ñw÷ðÊô€c˜º˜ÔJ'"µj=Ÿ'Õp¦K0ChÜ45j0¾…H++óÎ4ud\bj” ĬÖçðe J¦ô1Fˆùt½03€Cßèú£¼&2B?¡·Ì_ùýà \À´—"¶˜z™ÉN8ºuͨÍDrï‰9‰`Œ@—hK’Úk8Î"„`èGÁí„fÓ“ØË È>‚uCàÕr2:CƒÄqZP›=“ÜCOÍò… ¨äîéÏ)ñK™}%M¡¨Ä”$PG`ºŠLÙm%͉7zO\€é»½‘H6ƒ€oš‘ÅA€Àò¤#äžøWf;ú™€«Ò've*ðd?ÖS†wÒjé”ÙÔF ‹ ¢Îþ@|y6t‘p%b¼±½43”†7€lúzÓîœI]«ö.©¾/dÿD6,;ÛaÀÈ–’oÈÌiëÄ›uÈàÀ,6è~Ú–ˆw•m(¯rÙì{@¬=臟$âÛ1–Êb“=èÆiÞùôû4•s='ì“3t>üCÎ\bçäèçÔ/…ˆ ¼ˆG*È«´f *Î íähÀÂàÐ:Õ¹YgLj®Î@øþ ›  F%ɹ–â‹“±¨9ã=…&“Co×寶`Nàİ,+zÎblœ&°8$ºÌKÜ9/a•¸PÅs yŽmœ‰·9?hÌ s?ÎÌc•Ça ¬”ÕvÀ¬Øð‚/pn9/yv¦ÊªÒ¢C5Þ‹=Ç¢¦³ç¬žñÎÅýÊå«ÌìË}*saˆÕ¬ú¡€ÃGhï.x”+&Ÿ`Ûó¹·Ùa1›œµA—tHx {Õ¯Œ€7bj%"ì Þ¤.Z±ql‚df¶+kÈ&ÈlÏ Õ P&ÊáŠ[LâÃYcEþ¨* †°¢=X˜Éް]0Ýw9Ë'Ÿ Ó†…-E\Å+—”ÄÒæR-Î kX&÷Dy;»xŒ+(.ªDW¥èaÒºs)›®ÑÊÌ•0ƒRïf8“Ùi¿ ÄbR=.°Ì…\é'“cMG UˆF +|ÓÕhè°Ü¸²BÏÖµ£“}h$Cã: põE³Á½ƒIF®Q·LLE‚%ÕPפ0Ô±7UÊ®ÐC̓k:± ±Õ¹êÆV¹8›§îzœTSe¾ ˜®È}e³û™F ›^Œàê¦t4H¾M5eªbiŠ:k°0£±IË•\6¡Á’äº0h$ÀÁEpU¡•s¥œ~æwªæ #%ƒJ"„«‚HÉØ ®Ãã£pâ\Ó¦©šYð]E s¡ÇqÇÙò+Ø’½¿jq„"Ф3väFˆÄï³ Ÿ†tø}±¾Ê•úåªÍ —2~ChVßÉ0ŽM†Ã<>_5Ójp‘M¾‚I¾<Ž85ËèÀTYnî|K8ĵÚ:Š„Ùs¨Ì7¡#jÍfuàÍ7µcs¾ñÀkއ£|~Œô£æxas$Vô£[G=ÝŸ¬‰@1X Óè‰Ã¡5Ù) ©Q'ÇU‚9üÚP:Gi"Žk4ÓÁÞ†´:$ì$ØQc%Ò-7¤Üh'ù†QSp ÛyDZ†»Å8(îœèܽbçα ]w¦æ|Ãü©w&é`¾3RÇü†ë¦gÌn=pæ]®ÔL¾\5aÀ¬./¸M£‘+Üòáò‡ÛF¶®T¢LuU%7ƸPä6›FxrÓN¹Ï¬?.ˆ+Q-°‰%É„:74¹Üçö¨F>t³•Ë‘nÙrYÓ `•DêV2\ÝæÂ­ÛÛØÍr.+»áÎåébà«ån·º|î–B“àÝžØúnv4}À “®2˜ù²Ñ,ÜÈ鈙A]Iqci£Ì¸IÕt7ººZä¶ÙJyr®«Xnãu5ÌMÁºæcWëܨlšŸ›ž±ÜfФ±]Ùt[w£”ºIÜu×b67õ¶˜×k5xkÁ»ºÌ£`®c*5H­LE­z)¦<8Æ ¶¥¨ñÔKVkuŸn¾Aô`˜æ‹2®ÐÁH¬‘†C òDÙxé Šgå_Y0M\&a1mL,-CòSôc¢7± Rc$å.ƒRJO·”7,ó¦™Á7å æaó¤}©`Ae* ,*SVƒJej |òé7|ÊW©F±|1 ë*ëmpØ¥Û^וÿ¨>+æ¡{øC·íÀ‚øçâÄû°«J_{©Œp„‚¥û†Th­…ñ›Á¼F|ó2+˜ Qš™ðÙ^ ¢~ EË}ð ®gž†ØlÔr  LùÞ¼.¡ø”÷ÙÙ§6.¿ÏÇÖÆ‹O|ÙâÛN £3«Ì‹åïÚ«ITñ¢÷_]Ê¿!fó¬A]Ü5ŠY¥êǯèûÞ˜.ÃW¡é³ 1õ´°ÐN{Š}Kß´Æc0Œgb=ºÜgc/}­¿ñÍËfØÜ !5$NœÇ©«L³G(§vôád/ë# +GÙû’_…Wc‚©È;\b'¸´7¹MIGéʨKyeM…ÊÐü>¾Q´ú_‚`Gqeù»úb„ l®ÈAEÖñ ð;À 9(wéI,ýØÑÔ·½i¨øü÷Ë!×À§>éYf-$Ãî²Oñ~VßöBV{út`+V-„Yh½Èê-\.hmp1ÖY•¢Ég‘Œ9|{ù ÷‰Òs”ð²¢TC/a­xMOª½Ëü®ÀAzhúp#¡à$ÊÍ:Ož´‘ >š(®Ì¬œA x%*pívypPë\^ë#ñ: ‘1lB^ “‡ÛÐ`¦ ¢Y‚s´€Š­˜±K£¥²cGàËâÜ‹Ñâr E¬yWBÓ¾qþñ‘í`lÁGƒ‹ŒªúJ\Ílç±ÉÈ$uõü/tÅͼâAvuðùϳÅýØÁò#! õZf¨{€ë|Í3@†Gl_ø êíÃÖv!´m†p±èNÌìzÓ Hì뻼£n¹úhH yQ»ƒ ’ûyøÐa1aµôO¬U›2`MI]Mdºç2°Ÿ¨M+ ˜ðl‘'u ¤r¥~–e“êa0³…\²`¶òœ®7à>ì´²%h‹Õv%þ,yNöׂ¦Èºa +m"ðÞ5%§¬ü’r“îøÒŒæe~€lL~ÈlØvëo+Ö¦ j›¦røëÙ,DÂf½[™BpåÔ “­t!^¶Ê(ê]Sˆ¡m®Kz¹¦ªo6 øVË%(`ÀRÈCöW™‘%„jD7*!"ñÏÎÿË?½ÌF™Ì¡ˆ•´ðC g¶[8š1²Ëá¡æJëâöHl ŸÛ¤z‹àU7U&5xØpdÈê6h–¾éˆ.Nd!EÂr5P;ö3Ũ© 6rŒ%°v¥• ƒn °#ƒ®ÏjÈáiL>ù•‰Ǩñl™£×è臄'áÂ3Yp&âqÈé`§"‡›—­1é“p +A°'ÇN²î–aóÂÄýÓ8O€ÁF2GqÍ`¸ &GÄÂ#H8ë"À?8Ñ´|û|Ò %8^½l6¿XÊc÷ˆºÀ`¿[8àÂE~_ùnϰ¶õƼ^P#ÎØ÷Ãî\fú¡fY웯ôw‰Ó,ã‹=0r Ã-4ÖOA•dvO€ûOgêã×ÊxE,½&Îb‡/y?÷@³ô>Ï?÷Ð$ÿÐmíGi›4uÄg‡ªCîá”9qæ9I9§Y3ûÌ~¨ÈK‹ËµvÒOr`,pd„†EÐÁ~bµo’8pÀýbb)Û~‘9—þ)‹ºCÞ$1!±À^¡]ѧ<8Éý,½Âz¥¨!YàÛî0„œ,œw‰™Â  ˜Àû^|iç§JMˆ%kZ{üW·õöÞÕ ²õꕽj:0]aµ¡ÝË3µúB ³£Êç2ð|f_-Ÿ,¢ÚƒL_=©pe —O>bŽÙwG–Z¶+¦ºi¬¿tD²ûë”ê&`LAÆ2bÞ}ðÌÒ0VßH²]-ÂÀçrû]ûlÑ}ÌÛʬjÖòYåÙ‡½aTÓV¨+€¢o?çâ'" ^î³MQú²ÍÓ¾Ó¶X›mÃ2~Û­Íwú®öùðïsæ'¤žÛr’l ª³¦ë´>‘†ª]‘ 6aü⇯}÷ýÝëOw߀,5dhqr@Û`yd‹c•l—¬ç1—H¢ +@WÅ ÅR€#ò¯=ý§vþ:ø¹˜$,AÐÓ¡¤à¾Û]«DæÖò!eñÖµ é JÔ 0ŽÌ†Krç‹ÿ°ùòÌÔ ìÛì™i –¦™¬4@˜¦OMü@4;Û -þÏ#òX´Èf ®ãÿ1þž]y,þOªå]ãÿüñy¬u€u[{ÎÁÊ£%¸\ÿGI/×C¼)Ãp€QÐ6x%áóYÃç!Sjˆ=ÂÖPਓí^ͯhýà¥Õk£ ú}Ÿ˜˜tX†ƒ¦HWГÜ4N–`Öéæp¤Î“¦X,Á_»ó´OÊÌÿ0¡NUf8—I°‚¥æ på¼[Só°Ó’’™ž^’®ÇRóÀŒi”§æ×;DÔ©yØEŒã ,5^ÈŠB“šj\àÃl©y.Æo©ypVùMjhe¬vxjž9p—§æ!³5©yû¦\RóÆþAm-5 ~<¼&5'¹:ä©yØÛ‡ÀSîÀ¿Oý<«Ô<¼˜Æê¾Y‘-5f,µÑ§Ð›~»fæ9”YŠ%æ³ëMbx™KÌ3À%#Ä*1Ï@ +¨àƒub¸é0Y¶Ä<à þƒž˜{!ª7‰yð~8y^è”t¦’—çr)Éãm²T52—§i‰€+S\ðê1Y€0hösd®LsÆô2À^e’¡©B† ßcì&C˜ñ‚¼82^™àÿV#|zhPd2´çÈÜ–XîlÁøš#â#ˆ½aÈÀØ9¤±EØóŠŸ4d€è±#xRð‰÷_ /ìvoÈ6P–ÓT!8Õ3ký† ÀÿŒý¸\Ê/F™Wçµz¨ÕjÄð +#\|Ï€´<‘èá"W;àÈ]Zt$ôHb dàþ÷·ÀÀç½_:x>\à/iüsÀu†ÙÍÿUF&á1W‘“MNðÓàJfëL~°K‹Ò[ÉH»dqœ —ìF_G{ú] +%^×5ŠóÖãŽ:¶i&1ÒØ2=³U¦óP·êHVÐMð wÅ—1[ÓxXæFâY[‚f™!áZ Áñí| 5"f­Ct™AÇ´@Þ@r!«.ê‹™&±fh‚!ô(K Qä +J4€…ÃMœ'¨ >fÎĽ^¯è†´Å0ÙHüiK 3x§Xº4dO[¸´ðȜڨj'¡| bÉ’…güC +M7:g<ÁB½AÖ™!X08ó ðþ&f*{+[h9”Áeä° >GÏ^P‡¨cP²–vŒ}3'TQ­Ý.Ôñðå¢H]pîæ`û7‚2Àìê¸{žlV‹Î‡÷26”…ïÛ¿ë»f‰Xä š*¯f¢Z'À·òÔZÚ¸ÿ/ Mš—€ ã›äJ Ø’ú$ Ô$X2^:¥+âð|Ö| +`§ ²Ô)u0cž`©x‰3ÙIò8‡Iª*Å|ÍX.°D ¸¾fŠ€äp‚ëtLe%kI'p¤Ùj`i) 1´R'¯‰Ø;–âÜæVË9B½J¢ @Å N¦ž3L –mßÅy7딘١J©ÃA°—ZflLÊ:ý‘ã +-IºfÞciD‚%Ь“‘£§$áȸýZÒP€}Õ©MÜÀÆÒü'ò8FĤ0dÁ¶ì* +à¶ÆX²•V©ßMÇ‚À +ìê¤-¼‹yà’Ù…ŸbQKS¿à|køª¥‡ayœ¥qáÔ’Ì ÙU©h†r¶|5EB e müBöÆ/Êûu¯!*’Ž–ÓëK’pÿ=ð 6AËóöÏævÑGBÌ„“ÚPqx8ËFó=ºáü«±]a•óy“Š S>wˆâ]jó ØlààÒ¬=Å‘\¾–ø->_l°1 ¸ÝqåûQóüUº±ûƹèªÝtø%ØešYÒBA ë‰ÓÔû|Ž2Õv€ürМ†eI­UÞŽ9µ“‡T¤÷¨G“¹SÛ”X‹ÚU-oñ¦è$€)ñØP o0ÏÎQEÈ ÍÔ31k3|Édx°,nž' „›^Òä#’‹ÒÆI#¶Œv2—os–-|æ4x09©4¼@9¿J IÕ{#øð!b^'ÐYf‰l5Öa®Æ[øÍSËhÁNù¡LŠtbŽ*p.‚A5¼î!}I17@^á‹=ó×Ypô›Jûh‹uó©i2àèü•ü7ºbžþF¡ ÁÓ…ò@=_I‹å+ ^Çüù¾ðÐ@Ý8%zPwWd¨[Ðcmz¸¢îã&¨ÑoÒÐG; %8RLC©‡Ê#-íÐy0¦Ì&`SŽn‰êÔ£íqŸzüÛT7J#<ˆÔˆHIt£”¦Ís£äÈcV^YT«Ñ´&öÕèžEÈ]ôÚB>ëX[£±’«4؃vN7±½FÌ=ØÉ½‡ ¶PE;óð˜cç/—ìl¨‰_vnåqÎÎÐ,ÚÙ^-íÌÑ£ªzäµ³Ù&BÛ¹quŸ2lö®®TQáÕU7ñ º BDˆî²†¬»8â1íåJû^®ZŒ¼‰?FïBRnï²”‡å»´å¡û*’5þ&¶y“ëÕâ§Z¨\HuVdÕÒÕˆ»ns©Ø-f.7ËZ-^»ÎÅp7Ñ™ î†¼Fœw{Ÿ ýntµÀ ‡öàöEW2Üézˆ[*uÅ홦ԘÁÓµ7‹Vª‘ÛN]}róªkXn…mô07Öººæö\SèÜêÛ¨}å6SÍ|ì꣙-ÓmÑ®Œ{µé«Å®]«µà¬\F\ýåA0ß1 ™‰-ÏD­GÍ¡¨ÛáÓÈÀ‰ç¯ôv8NS¬2Ü2ÕíZW)ÞV§²ÁÂ1x`h;Í,Uî]DŒCªN4XB.Y|X4g%«¿ÉðÒA$þº:‹Êà–2ö:‰£ 7e Ø)“Uã?eR &ò‰7É×§›| ‘*+mÕ¥§^øž~%‰ Žu“üH { ДpcÓ$š+˜äÕé# GN£ê÷¥A3Z*ŠÀÔ{•C¢ºM[”®,ùEye$£ Íïóá[‹¯|Ù›i+Íؤ±)5ûLÑ}$?ÿ»Ébsy—& ®úñ+UF™rÕ2Ï€qD–×-;Mé»ÎbÉdšu¹õ>zéjõo^6ÂÖF€%Œ…½Š* 5­$4°ìP³föR€t†¡=ŸGoª’O!æ>þ%…Í(éGšX&¿ÉB³¬ÏŽe/k“héì¢Ú(ÙúË^(ÁJ`§°J`ã-ñŒŸCKMãê6wÉ),Ý詬Êø5Í:Snõ Õ©²×T¤Âî²ïð~VöBV*ôX%”úNõvQ™õâÀñÚÓP²Š@ÿYyª³@“X_²$%Ð<Ôæ¦‰L pa•‘¬Ì¿ QYùÉä¼ens¬”X.<)é4-]‹h½€9ê´.èo¬s×@Cá¨Lσ/ÁÛëL2¸*`¶%œaŶ©$ÔòýZç®ÁUIÖ_î)} R¹}'~ØSd\õgF‹Lóé@ iyƒM"85y3µx W €šÊ¬Éû"!új±|›¾˜4p¥,kN/üÁ÷…¡Ù?\z®÷§*É…];D½Ê ry—wd FÊ ëD$e`–°¤ Þ’š”¬•š2–$ŦËÒ¨”I­Ó­”qXZ–²@–ºÅ²Îðâëmi`Ê–°L1eëÔe|‹Yâß…–šÆ7k•¿Æ·´ßd»Þ»ñÃѼÍ‘JÏ™ÛNcóu~h}ü`ûD9h&Ô …O¼_£9Í +:iò•vòå»ÁÑì'‡¾».(抬¾Ù$àÖì5#ð”ö%{ÍKöšÏ +¿$ÏÎØ4M±•$0+L£$“àJ)zb¹$™J•aàÐfNc¦¹Ö†’^cÌØFTeaàmv¼³d ŒC—40])U¯r>à&…Uh©Ùâ4DáèUš È©2XÝí ½«$Ž…«WFeß6°AKÒøÈ$r€úœpŸ>K¹šª„Tó¼šR˜.ƒº ËÔñg{º.‚9†¶Ò–ª›4}AéÈR”Ö©ÊÀ,eB¼¥U(ßX§_(saiÊl ón³Z§|(³o©!Ê +Yúˆ²uš‰²àå>Û¥/Û<í;u‡ùÐ|úð}¯6Ÿi[ÚgÃw½Ï˜ŸŽffýù +”sf«´>ަúþ9²L”IyM¾Mw% –*ÝçâGUOwïEËlàù®&š¡ˆR[žï +–,.äù®Xœð,,–ïj„“~¨Ò]QKËzº«q©ßhù®à?"‰-ßJ>q&VÏw•SUšÓó]eÒò]AzàT0žïj„Ý{´Šb–ï +rÇ_Ïw…°HÎèù®WÂB—K¾+ØÝ9o¯'¼‚ð#5³,ãÜf‚Ö3^á¾<ÏUÆ+öœÁ*]¬æ±{ZÆ+NdzId@ŸŸÌ$»Jxu‘ïj;YÔ°HA½:Ýì2ìõçÇÝ«4ÃÚÐÃZÚf»Z'»Ú~y@JJÚ¹‡Ï9?×›)r¹|dÆ…¤#Þ$`Œ]C!äÙ™ƒVÍE!È[4ª¹¡ øSÕØƒ“çÙ)9û À±¦GÒ@$%b¢Šò59½áÎæÞÒ°èò+‰9‹åÙp$U„Ëfr€Ù(Êz¹”ÆÊ/¿½¦Gœàƒ4’íÍjÂD„¥òº1‘dJ½¾LŒI-±[¤Õ¡‰¿¸ö™ÕªÁ“èÉ*ÚDZs®ðÊÏù]qëÅq"ŠšöC©¡ƒM?L*y­œ!øjZ5žáä5Ì¥fOD­ÇÅÊZmŸˆtHÍãå¢9Þ{™ ãvÖZOZL(ö¨F‡JVo(öº­,QX´f*¿Ðªáê×y«o{ä¾À'[¤§ hOüB+—„/fžB-© ¾×*/E˜ó“Í©UhŠð·á +.Vʼn4NbêýTª=E¤}¥’'µ*¯6׳ÊQxeæJZ_*bÂá¶ÁZª˜G{PKUaöv§—´Â òdU›¬ôU„_&>AJcÅ"^>ØR)1¬gÍ+7G²T,¶£[ŠÛñ.Åk2à5’Z”2ÊFQJµåšò”ªÌF¡Jåf£b^ṡv^ Ú©¢‹vÊYŠJ×Ö‹O;!öòÔN¬½ŒuCԽܵ¯ˆí Â+g;‘©ÕÛÎo¼·ó¥?ò´`·ó//êí<΋7¬Ð‹„;ËôBâÎV½àxÃ~½0¹qi¯]\©~¹j‚×KwáÁëª72†×_wYÄJ´o\¨¤¿hÂW„wÉ+Ç7‚”W˜/÷YzʼZ}#¼yQ{ò¼ð½K©x¦kicµØ¤J‡½\òdU ”ª‘Pñ ìKì‚,t=þp“u3Œ¢ð…mdâŒd¶¼mMvÆ}=*d¹|'œª–ó +:&­CWŸû·¨@œ¤C„¤^ þ`<÷o +B†»9gžS"ÁÖʎ赪‘àg‡×HH}쮵€ŠðµnÅ‘!CW@ +8LÂÕ$!•ÓÔªS@–˜©]ÐÿCÓÄÔªoÀdÆTËÃc Õ¹"-žå Fa,÷‰Z Ê3,š)žøÂÀH¥Ÿâ Nþ£j,c ¼Ø¦ê欉%]%–÷M’½3N–s#`þ“ a†3t1Á€F €…àbHr!!ÙHR@‡JP4GÎo4KŽ^ÆYé^äTÆ €Lú9w̨À°H›b snÓȹ‹!ÀÉç„?T†ÃáT# à,aÓiÒÈ®È|é?ÿŽýqBÁŸAŽQ¹ad'ò¾Pü†ëù;ç…sÀ¼i†¶ô*)ø' ^ê’*ŸÊ1KÈ÷ãÓàÇ­L^4  L/ä*7_‚„Ü­Lùm¥;‡LºýmEdUCždÕIÀbØ¥ì 2`ÞwÀþxÝh4s’uÚ¶c‚ûÊl™Üm×&àl‘%Ý×xp«íŸ(#kP@¹ bð+²¤ªê—`ùÊ¡àr|.À-íè¦Ð«¼eGçŠØ9N¯Ó±Äaö‹~¤‘;\]8eŒRÄR:ÌåL$2Åå…Å'!ôÎh0&±((â¤É4&›V#éØ9#ûi€”N»ÓÙC{€$ìA¸¯÷ÄeY”Ѥ>Hr¥Âh‡²à& É6:?iÌ Ó?s½2c‚D©;`Ì2q\³Ye¨ ‘‹™ec¼ œkìÆ ù£‰5&ž8tfž +³÷+o”ñ²PPîS¹³Á1+åÂ(e-]$ˆƒœ’ßÄ”rÅÄ™ÄùïM¢4±]¤@G»#_ác8/­…­ÁÝ]KXB»Ô†ýʇÀd™nN:™Û$@\É\ +Î$Å„1تY°D™€Ð£ìŽ ‰¦þ.œ&Ø¢LˆMH+ÁB¬ »‰ó×Ó~c²hBq‚JÏ¿ δû%Ï” Ø ]È $„Wq\åCíÂzÊIY­ õi„ë$ŠEÿ”ÕyÚÕ\áTP®Fà +ÛäIU7ŒLÜL%I0x²(jª mjñ5<:ñ!ž¢ˆn¦%,XÒde)8…I·§)U &L&¦x¥1©9×4þ Å%|ÖâLš(ŽdŠæ™ô÷¹(„èhÑÄUq_˜±¥L¹äîY,0%”û²ìb®¬‚–a“šÂ~ÆÄ³cŠ/Ó~(dž °‚ŒÆ>”®D§¸ˆƕ픃¤l2Q•ò4Ž:¯¦¸'üÀmLÁO¨—¦b_g !œ0-ÅšŽâÂ)$PßRzQ?2ëé5p"ƒD÷•+Ó öžÄða8 ’Úˆ—ÄË¡"úÉžä +°ø}Âx_åJýÎrÕÇfÀO¿DÍW2ˆä3á(“M–aQÍ”*`寀–/Ã^Í:^Ý$è®›9ØMŒ./»Òeêb®¬eo·jºŒî–OãÝBÚˆûnIuµÀ­¦9˜I¶Ñ/Ür«Zˆ™v]Mqp£Î¸¡ØÕ7&»jäFçF…rã´«Zn¾6mÌ­ÜÒæÆpWîÜ`î + ÖE±Ü§ú¤[è]åtK~£šºÅß5Øâ`Jnñ¨•áÑ<Ë\iæA0ë1ÅôVf¢VÀGðztE}\æ:pKQæ'¨˜ nÕJÿˆZ œZÙÀ¦ü¬’€0"ñ x† òQ£Ï gMc¸E“¼’ +oL,,Cµ2dŠ‹„7PI¹Ï •Ò—Á.å•ϼi†f0Nùƒ{Ø’êŸj°P™ƒŽÊ´ÕS™^ƒ¢| ®ò¥ªQ-_Q¿Êª@vé[‚W¾ÄÒ] µ‘R Nþ{Ø›À'G H(¼’8ÉàÆ“K³ ¼@3â¦EÒîBÅ>ø ß ‰#h/Ðz¯–›ücx­$:e7›]‘­jƒòûÊÀÙp—ø²6ƒkY·šYqF¥º NYÕU¢ï¬‚™úCGOmË~eä[X“Ú¸Móý•žü‚¾ð©5|uBò&-œÉµÓ`%†A¼ó ,:{AvB¨Óå>|éký‘o^vÃæn©% @r8£…Ÿ¬Œ|šïüôÉÉl;ªOiî5ù‰_M\·˜¤x"õ7üc[¼¿Ü'ä£t¥ô¥¼±¢Be`vW»’³æó^‚ 'NP¿k..ƒ0‹É2ŠÄS]Yø–†T·éQ,=Ù}ß›šþ„©öøócN +h¥ox" êd£ºÏ?ÈûZ}â 5Xm¨×R8¢‘‚ÅnUv•õ]ˆ3gžø‰ëQâØ³hƼ¾‡ÁsûD‰„®"F½$¸²B³7o#kÓƒj3¯0¤láºpRaÍ–gvZ„9hz÷2xÁ°¶ŽOPÔ"P;ÀY¢gV«ê:¢âÛ€Ùc‡±?’µQ."§±”Ÿ¥/ò-Êò +èÝѦ±9¨8õ40.ï, ^ø£ŠqÍôû0SÝ•wl߈ÀA6.8ß°k¨ÆSõ…¸Êé¯}"2–»×¹BWœ¬¤™ÓÌ ­ú±Ì}ž-ŠÀÖV N•Ö¬#â81¦-7BŸ8,Ûw„¡Þ8l¨‚æ Îëâüb›0s±‰¾R…ÄÊqqŸ÷zªÏž²t.¯´‘±ø¿<\Ð,ÿÆZÁ)sÁ9³Ð2_À—y¬æ•ó›j¡DǨµQÊ +!NŠ=Õl%¡1†+ÚŠ3Z:IùoÙc/&WÛ9TªzàìOŸ£¸ÈøŒÀTØõ˶*|úlîI¶¥«ûtÛW}Ùñh^é‡HVΙݎcó‰åÔÚT”“mÓU(@=«…RØìjb+T¨N£ª:qÒ/ôËöDD½w +=´-¶A3/hë›M:þœá÷c¬Âïéˆùš¤^))þA’(¾Äß¿Äß?b6à‰Á>lYÑ/{ AÙ“–V‡#ç9ƒs'¡Ä‰ ‹@L¢' —%@ Ö…!ÿsê xoåA]6z (Þ }ÜÄϨ¥’–,À±ÝLh`_pHdT4 ø÷晚HRŠ>¨c'ìgöc\égSMÉc +ç9±gÏIÊ'qW(†‘–^=a)Ñç³ÅT–4”˹/á}H<V$F>áò7[Ð,Ilôrðžë— Áìª $6`ûy#ŠÙ³+PuøàLZÿ6rNÔ“ä +õ/DQŸ%ŠÏ"g£Íý ¦Fö~¦ÝÅ8vO*ÚnÛ­:&D±õq¿V—åšíDGQ³|GÊCÞ† ’6¡Ê}ˆœRæKeYàî\~ öLNÕÛ>Jëô^P4…©¤¦,WjÇ:¶æü½¯e³nbJŠl’Ñ +Ê>ôZzt†Mbb3‡ôl¥d¯Mç_@%Ù§Vgÿ‚ô°t±tÓ¨3l£ƒ¨4™ñ”Óû,‚,2XY†Ëš³àâ_&ËHÜ×~ ï_¡Ì‘ ó +1ªî›4øÖûBÖ(`ÏÕ;ÕÝÀT(—솳ž„€ƒcý3é¤Væ¯LD=vîö)›‚¸ï”©…™~ž¦2µ¼£â`e‘Ʊ…[!,slƒy›È’ûm¶)JO¶yÚ7Ú&+#³XFo¶ùJߨ>¾÷}ÆÊ©f¶œ%[ê¼é*]KÃäþi@â ÙâB¯ "1ØÛ]zx¢ B²uÁ±{D¨Üðm V^:œm°È-ÃN6XÉo>˜Æ7Š7òÖ¸Näjœn>Ku–ÈÎ>–Ó;Fa«Z€©¯^‰t,<g¬\ÖØuÎŒÃq©#Öˆ¯ÀÙ_Ëyâ>ú¦È¹|äÀƒsòuq‰ð™ô9I¼Yå3}2öŽÉŸ§9ÎECâÌ€“¤be? ~õ2RÑÒò»]H¾t¨HqãRöp>yR}eù¾Q‚ã–Eà[ßsDNµ’=þÌÉ?ˆÍÐ'ÁåhIZB¢JþÁ±ÿ{o׳;réýý‡> 0 ²ªø•3kÇ™q¢A ÇHbACÙêñt2­dY‚ÿ}xÝ룪ÈÝRKÚO&}"õ»6ù<|ÈbÕªõq_ôO­è|ÿùlËÚy??˾ÿ`õáÛ7%øÛ¨þñC¿]ç*ÏØ~Tÿø,ê”l˜Òó8ëù3iüœu.ÇEöYçžÅÛ¾ŸY‡…bÖ9j@"bÚ!>a°²qÚQ5Àцi –èÁ9íœN‡˜§­†â®Å´sâðo°iè¤}ç8ípܲîôÃ*' HN;ì×lR§ËÃm}ÚS!µ²œvÂßÏyÚQ”ӮħêS3‹YGÕÒjg¶$ƒÃfê²n‡¦õYçý4ÿä©§{è 6ÂCÌ<_¾¦žO¾»I¢f¼îrßNŠ„‰%~ßùÔÌ~yohq…ÈŠØÆç9õüþoŸfž?êÛíüÏ7óüþ›ûÿ‰çö¤IZ§¾,DCž^z{¨¹¨IͪHÓQ¨¾Y©€Ñê½Ýƒ«J{S¯óeÂ_MƒŽX-ëýœ—ꔀߪ5tT´«¦ªVÈDºÕ|ñY»ú +ÕÍYàƒÒ¾¢¶r+¦œ­UÓu8T9w:ZÂDmW“9Z¬Fi+kʾ__â-\¨ÝÔØÚáçKªõYÁ@‘M +gJT¯hègò\]]‡V±B±¢DrØ&p¦ ,É·‘ÍtChÄ”@mîRëB̘­TßWh—ªϸÔc7ÚŽdêš +È @púºªÿùüÿÌÍ—Êܨ°·åük.Òj»ßlb4ç}i_ZÈc#ÔAœ æDˆPåØ'-2ŒCMY[áЬòåŠdóü'?aA䌕@B¾hÚP¨æ!_ªl=¾çäC³ýÜÔCèÁšþí¹¶Fq÷IÕÚ½Uü|îÒ÷Þàÿ¢6† ;BÄìÚ¾ñ$U@v?xkò‡À†Îc*+ÊRå’.´¿²4ÈÛ™K³™Ã!hå³ÚiMù&¼C/NÔ 3¹‰œeAa1¥)¦–`ÈÅŒÝ$†Æ$µ2Ìøª…èýB M + ú—{jÖNÜ›ó + "ïúç'¸ÄÒnÔ%íóE…–Ñuºž  oMÚ4Oðá6/V¿2¦º³?ø—m«Ô>¹5*ÙÛƒO1¡š°+y´Fë!œe<Ì÷–ª#­z<®N"ãKº]ö«Ñ#å׬»‹|QYª§ëV™XФ/«Ó`k™;O£­Ó$8ýàEÿÒ¼l°8Þ%v³Ê@»Íþ£ÙÖ’­¨$ã è!j£»IˆµƒèQøMÔE²¬UéÒjLï§øax¾*ŒŸVcÖƒ ÆjLÁŠÒ\UÂ"uºq5æ!s5Ök«ì‹1¢šÜÈq)F-Eµ¹£á¶^®¦¥Xt•6-ŬF5ºXЉ©&QáK1Úojd™–b®ÂÚ¯m-&} +Sk1GØ­×b¤i6K¹#8j,ÛX‹KÛ¬pZ‹‘!½gòa-æL{>¾ôš¶ úGÃZÌõ+ukqQЄ{ãk1ú©v©ãZŒ*i“>Š­Å…JK+¯¯Åï§ÿY²%(íké’cµµø~3=û°ûRVå3Çpsb)Î|ÉU½|öË{Ow:”îõ ÷(ªÉölÍÛ´†¼ k°¡W¯O~?ã`!aã‹qËÌÉ»€/H1u–X¯Ï¶…ø—NÜþgº«IJñ»q1n÷óòĨ/ÆM›ücï‹17-ͼ7‚Š +ÇbÜËš2©/ÆtšÈ˸³#¯›´P}1VW¢ô#ÆÅ¸"Ö®™ªÅøýb1nê~ç_ÆÅ˜&6 cçbÜD]×¾«_MKè¸"Ód¦&Ä\‘yOÚÖdz;íêÆ™+Üúj¬V‰¶Ä:K[—ë2˱ÃQ§ã<è’ë1·Ã q†õ˜Ïóîë1Á•°|=nT·ý辫©F÷&×cëªØ‰õ˜•C7kZ êH1Öcz΄lÌõ˜`™‹Cë17ßR ±ÓŒ%©•XŽßÏ1–ãŒãäÏŸ¢rŠÇ+)Q9%ÂIneTNº3éFTŽçNÃbå §=.ƒr*;rfNÆäTu*!W­¹¯“³QîkÄäPþ9˱ö˜_°íGë19²9ÇæµT“ãŠNž`Æä¸—$l"&ǧ«¯pŠÉ1$«tP"&§š+”ô3&Ç—/û¡5ÉñÖHè19SÁY†˜\eå_Jó<&§ãôP#(Ç¥éѽ柔ûƒëj†Å¾|†å¾üddë`·ŽÒý—£¹ïËz^€IÇÐØë¬›]mz|Ä#0÷å#2÷=ÀÁûéŸpö t GAÄá 뿈Òwî á~«”gÚß®góbÐØßÂcn +Úçþ6 +…§ý­Ž»jéû[}–w±¿­ÒÆi 2È +–b»ž¶^MÛ[·*zý‚×îv¥Cìø´»%!¡âÒÜÝZúA~êL‡üýiwËIš÷rw«ÇñÏííZ<¯=mo ïKd0¶·àRÔy˜Û[¥eÿÊØÞ‡EêTRIeØÞNyÜÞr­‚JäöVT‘Ë•í´½…²7'€æþ,G±]§ïoÅ„:U3æ\áË}/’û[øìÖ û[1§ªü'ßßéØNoÕÉý-@õý-))m^1ÖÓ—Ì7Eì¦MKM ˆ9ˆ·û±áüÝk»IH^Þîû8µYÃt3Z:XÖ,ókʇ£È.ž•dÂVûù°ÎuBCCN¼jö=GTÏåqËå’cÒ„ „ÀÇr¹à…nå¹”ÍÎ,æ¼òIG^ê\vNÚšÂ)D­Ú +;Ï}«¢Ê)5¬æÞ•e5Å ~%¡íUµ„Þ¼DàÝØÔ÷d_YòÑæX"?|@Ú6ì5ˆùÓã„Øí‘²ö£ÖPBÞ‹žÞU?»ùà>/Éê+¡éñ’º.‰©T—-^ûׂSª‹ }pgÉ"ö¢!lPÜ%…» Ó‹¨ +šÅ§Ômï÷@½Â|§iNÊ}vû´ø†9 î\@l÷3›m + +u„Ë%Ep(!æPŠÀ¹^Í}¶Üñyä-A âD•Ø÷ÊÎBU+Iqåª7õ…ÛD=$Äè1çƒyÄÕpµÙ¯æ^¨m"-‰åÁ~ô7Ç­¾-á-RÒ-‹¹„Œ}í@âîÜsÔý“h½ÆçD£ÂtžQFº±šÐW¦W“Æ”%(欒会M'ë%PNzuº×¬*AŽ@eíXLIý–x^" e÷üNЈÅ +XW…‡x‹©Ó˜zÕõÌ;#ÚäŠ;¥u““Ç%lÆ’õ÷:n7͆ÛÅñm¨6´ÎFücGd‰VZÙ/ÿÊX”›¦6i!ÿ³-Šñúi'ÁC¥g̯5Úx¿¥âvïžkM K܇U4‰¬ì¦&KTs1óì÷K(‘#TõÅìlräUUosĹ8Y¶m‘ZßB´®EµÑý)Ÿw™9u%²RŒ~ýªZlfX¼r¨öŒ^Ã4D¬Næ‘Ø„pY{ˆ=U×eY‘ª‘Ž WdßQ â;v²Rrà‘”Ê£rNßpé;/kÈÓgQA •Î <‚k‹ +ëî…Ÿ2‡{üxÍóq8<ƒäS<6='‘•¢6•œ ½¼ +á«õ2ñ[gQÇ9ýñÂùoX\õ•3eAÉfSÑçâ`ÒPÉ}`±Mp$K1ŽÅkÐqäv0 g¥vUªç„ÿ°¯Ä‹änl&ï•cˆØíqc¢î_-*i/J£äóК­>+A;£f$Û.ÓÒ韔–é Óš×Eh˜Ç–WN.·ª›~aÖÂåhT»kðÄݺ?Ü8šÓME†ÕÆuÜüæ{•þ€$ʺ<äV¬¢?p.òmsP ;ØžcgGA‰3ÇÑŽ6CêR@yN£u= +£Z^§M!>ò-„¾•ù ‘Z5óQ¼H„ITb™/µTM/¥®Cw;^^éßî×Ö_p>ü ?ašh¾½ÊqôùánÅÅsNAç]!—iî)êLÃ3Š9ªœêÎy Éï&Hà8ß‘SNH΋8•ªúɹ“«¸wÌmžc9î¢.*çbµË éZßì—ÇY½ay 9ù×pqrÀm–dS.$vk›ûæ¹à UMY¬K¿ÕܯU¾xUIù¨Óø·K8ê¼ò„‹%!ƒU!âÅë.‘1…¾úòÌàeNŒ¼Æ…>­á®Ûy/Òe´7^âìZ ŽÍšÑ]ûÞXJã–ÁIkº=DkÒ5R¡è¹\³¥n¢¦ý8z5fÂÛ<õ?»lípžSºv÷è±u÷º5îôä&ò†i?Þd¶¦Ã©}˜Ê*&Ç´^ÖYÑX¾Iw#œ\æ)7NÎ0ÛyXÓiVE2é”t¬uZ¥&¼†›“Ž:ÛtA‡Ó™g‡«ñèóóÞX¾&¶¤-Û‡‚Ê;çi›A‚‹òˆÜ(G 0w,¼¼ŠO;^Þ˜Wn€”\¤ü/7I6S² 7SÌ–ð°|Ç%@@D?ŒíEÏñQç­›hZ×c‹'ÞÃ9·löåMÛÅ~\l+¹öS©ÒØz2)*¥:mQ•±%[Y%=yˆí®Úh5žb[lW[M8¶@)=ƒ`ëá¶{A{u,Ò!Õ}e믜%«ÕY¤6Gƒ hƒ­&¯6#V_cIKÚ¾ø¼êJP6ùs&c];æk³`~A±^1ù_¢©Ôž3y0Û¢–¦ßIþ·úr:,x¼}Äz‹œgV …ì‹ ]+>k§ñY-Ç)á¬Lû¬ÍûfûwÞ‹œå§kÀ¶kÀÄoPåÛeA©þ[Á­©n*ï©|ò¾ñÅ[ãúýÝ]·?ZËÙögEÚÒⵋgz8à£?÷­¶RÖY ›ãˆŽ~}޵{e2«aä*b;÷«¯öi1?Á½‚á¸ð'h–¶\·Ø*×ìaðò_‚I¤·Ò-áÕ°UÜãi¤÷C}Ùî Qu)‚´(S¹—Ù‘âåQ23}2å«¥˜®cC¥ á)Øfm.Wn +I +wQ£/škÓ­$¬,¿7O^@ÍþéŸV%Ë×-ï•PÞP?pø»œ©!ò÷:ÎýbúOl+¾3_^–³{Øw4< +»"ª3x¡Ó[ç´#¼zkî‰bµðþÕ^õJù¡×þÍ–Ýe?sÃßt3>¥oJj¤ÛsóB7•ÒÞrîת^:!5f /çû%ƪr‘öÐ}_ų¶Ù!ö^ +²ãÒåM¿çйØËqœUHøvÏf‰aS¨ty]£>Î7<ýR)¡o0õùÍ Ù„Íã“\Æ(6« Ó{Ë|Ñ÷³z.ÛÙ·½LúˆÚ¶×wÇLâò`b­2³²Ô¾ÑænH{ò£ïŒWvö<¬ãÜ,-'cs/øÎ¶õ.:8sEw7üèK·9 +Œ¾~S=îÀaž£÷Ð]øÅvK[­.i +aä…d8$Ó÷4©ªMó!¡•<Èc/ýcÂ0}[ó¢"ÔÓ/nûq±•ìYúØnölþ¸-íYÿؾöÊ€Øâö +‚q+Ü¢ƒ<·Ìº +-=±­Öt«{1n¿›°GÛÖ·étdÝÀÞ·òí¥—²çŽùé2dd€¥PBFX¢„X CÌÁVêÁÈ÷[×zÐB3"`9#¸Ñä+³¹Š8ûL’~\TúgEÐ¥gg>N×Aœü ëQ*5iÄ„ú݈¸QÞ´1¼Ôïm„¡úýPUNcH«?Ï}õgá±wu ßù£xç÷}CnYHäàùÖg7­ÿ¤eÑ”q(lRî¡°F…ê_uÙ¹ÅÞ¤ÅêPûqôShU¼?Áª¨$@5×~ÜeWÿ¬{r*„úw†ÅF…_ZÖ¯þ²ßûWþ8(>)î« Ö¾šw{ ¼óíl­@ÉMð^ª;wž9G|ômØ|”â¡m>¨[ü ?úþƬ­z»]ß«™`ùáLWìbãç&yX\{~Ôë7~üq0|r0 š)çoœðH¥›šoWQæ’0K¼øÄ"BN/j‘¬7}[yÏìKò¥gÙíjŽú÷ã|éŸMÿÎqBê×–Çõë÷¹íý;œ>= ⵤV@Ûèo'+ +þªFˆºDŒâ +ÎÈ8¿òsø °Ä~§#JäÑäk¿ìP¡C|8¨  Õ˜DúaýÅG½~ã³ÃS>‚]¶ò\“Ïp;^Ú`§UÛ_ÒÛ$í>=rn—ö[(à®YPªZ¡è!˜„Œ'ù¶ˆf¦î0¹ßš³”X”ÔÐûJ‰›ÿ)©Þé© q!pKÅ`;Ëö|¢ò޶G¦»”~ÖÍõãùº¢¨\lŒûLk°ËD¦­¤] ´âJ'},J²ké„T;¨õ-¦YØyXþü¨|I¦¯Œw)¯,ß¶¼ú|+§_™ooÞ|Ãã†åD0Ýל0òþ礒Ï('ŸéYæ$•Ï<ç±yÓøÉy1ÆÙ{î|ϱ?9ŸNð{DwpZ«·‹`áÜý„ MõÏ"à?Š€ÿ¿ÖB>õ»e yö»e yö»õò±ß-[ȳß-[ȳß-[ȧ~·l!Ï~·l!ûݲƒ<úÝÞ¿àÕ@>õ»eyö»eyö»eùÔô– äÙô äÙó–äSÏ›ugÃ[vg+[vOoÙA>²}Ñò–äSË[vgË[vgË[vO-oÙBÞ[Þ¢…¼·¼EùÔò-äÙò–-äÙò–-äSË[¶gË[´GÇÛûA~±Ék¢ÂùˆC^mu¬b—W#½eü]—W£]¡W Ⱥ¼Ú*½ç‡K^aiøÏW[#³cA5—W[)l€½›òjTšêg¤ºe×m—WCûS”ØW[O¯wNy5>[/•hòjë¹t5>j?}µÅG W‡¾šDkȃ¦¾‘j±K}5ô·òåN}µu·eµë«­Oµ°Ø™¡°Æ{AÚ½+¬Áø\J¬AΫM‰5ü™ëEÖ¨ -[ùâ= +>üäsˆ¬M`oü§ ~J”=Ö.õf“äC`íS +g/yµÊ?Þÿ¹›ÄOWXÄð?y6új SNöýeúÇ|»äÕ6È,'$Ïýþ¶Ï«Fû‰[ûŸAßùŸ'èÒE†Æ©KLÅŒÔ%¦bFJ‰©iFJ‰©œ‘Bb*'$—˜š¦£”˜Êé(%¦b:ê +Sãt”S1¥ÄTNG)15MG)1•óQ™òù¨kLóQטŠù¨kLÅ|Ô5¦Æù¨kLÅ|Ô5¦böé"Sã|ÔU¦b>ê*S1u™©q>ê2S1u¡©˜ÞcàÏœþ,Ç®éhTžž"S5§£{G>©L©éÙ4ž–A¦ê¡1EøöžÖÍjaF©Õ¦£ö©ï–À”iM2Ý_õÓ?â»C^ +F¼ÍFõøÐñ‡&#äÙ'mÔÙïÚ:¡³ßµuBgÖÖ ý^œçÐ)­“ƒ£´N¨ìwiPÙïÒ:¡²?Kë„Ê~—Ö •ý.­*û³´N¨ìwi–Jˆ!­*û³´N¨ìwiPÙ²b^Î=Ië¤Ê~Jë¤Ê~jë¤Êþ¤­“*û©­“2û©­3=Ç4—ü™ý?$û–ÕùòÓ¢4¡U?ëê¸Ö½ò)}Ôã÷|½w¡Œíþ÷{ô=¤ö¿|jíÏLº:ìè>›®Îÿäcÿta?÷CêrÌ&ñ;•·455bjÂhES$lÄ99ä>¯‡-­»Ÿ_z:JX*ž]]àšÐ&+ÕI÷‰Q7Ü,ˆ©ðµ§Ÿ,๵¡k{¹¬ BzWvb4ílže.Рʢq»v=IOÿÒýò÷önm€‡Ãvÿ‘ñIôߪyúFÍxPyet^Y†_‹ê‚²F_óô­¼Å2µlEv ü@«Ù¡ œ„.?p=½gñð¦Õ‹º½4S³ey9Š4á¢VOÈ[«Ùi i}ce•äŸ yt÷hä]Ñô[ô›×è>!ŽÞ,izÏ=!Ë~¨™Ä…÷tUI àR¢ˆwûMÕj¢/À㹤ÑV­d]Mµ•`%½Ð^ô¿0ÙëR—ýñ°%õu*„æ 7i' ¯ Åbë÷Â쳬Ͻ’ÔÕ‰÷,«EÕZ*…ÆÓjY¹†íÞ_æülÝx4¸ò X´š¨ ”¼VIûKˆÅŸäªÕl±=ä²ì&²d­^…Ïj&bBaQ´—ö5{Àqj%§ËRìë^ à$ú.>ú[ãÖÝÕbVÍ« –ý°US º{½ú…°žÖر^ÞuOD¢N¦ITS߯×b;•˜3%Æ÷nµiÖóD×MJq_ín¯®ìŒl„2óXÔlÂl¨rF5p„„;V#(®™º¢Yí÷TaÏÒ{(¤ßÄî=‚jµsÖ°$4v\“3ÿ{¿‹Ö¹|]&Ä¡+i‹ÉPÞWc©%ã\ÒËíÑ+ÁO”ó¦(+/k9¬æH­ü‡œÊÅë _ÚÕ^4?©Ê䀹›¾¥ºûµš¾$wf²®˜Ãüã=ÿ¤gh ªÕœZ õDNÐ0±¢ÎÛm»,¨ÖpwH®6rªMR&~¦Zm¤CY¼à”n4†Ë&|ÛÞ¼¯^4ßêçTÿ‘^ëEqý˜'ͺ¼µÄfÓæ­*HHáu1?X;_ ÿ +HýR|V´÷à#ÜâÞþï YW¸Ì‚›‘¨Õû»µ`”þDÖæº,´ý‰`½*¼¥FìÝêÁHÚY‰üNF¼~ÃyÙÕ™_gâ³܎èãj†yMwY¹¹Û‰æußXôÏf—ßÝ@,(ïl;L‚‹É~ÕWn»YhsVWJ·œÍ‚KºØ´Æ…ðíj©ûì^IŠ«©™Þ¾³…'Ç‘º6¥ø¬´Lߙּ6fWµƒçõƒ5XÖòü1Bó~Ð—¸e„âÈáÎw)6˜Oà^˜}°ÇS*»¯VÓÓäñKM!Ÿzk ÍqÏ™võóZD<êãŒv5û‘1—Ã1§1{mÖø˜Cá+ÿÍü‡WÙNïÈéͦù*­Ì8Ú@úÛ¶Òª§Ú°é¥ä¸ÑùîÒiнÏêúbã$€h2ê9WÐôT‡Ù„À@Ý“ŽªëŽÚç&mUÖ>y¡TwnóǶGýO1²ñ+nÐd‰{A‹ä4§îÞÌ”SïíË1;#üÞÎy¿\% fú5œš¾Ü ©ÃǪ¡ûH¿¦¬¹ºÐ(VP¬B´žáe’öÅJý›_þTtÇcÕ£bL‘š\ïá¸ÔkVÐÑèi¥]]õ=ÖãÐïKvZ¦•=­éð±Z?ÓG _LŽáäK§N—ã¾BÃH|Â2º/iM7‡”º·Ó¢ZÍÒ“ËTª7¢çqu3:|w¿èõBßæ¦ôæèÔÔSK*BÝéÉ3äm’ˆVzÅk-º—I[µT¿'ot%³×îµâDéw‡_K2ÞzÉ÷÷tñ…ð‘Qî6õ~w£×ÅEœ&w;¼™pÊ/îxݺÛNrZ$£wvZ›€mï=Òlˆ{Y—ʰ™@-R-·±çØÏŶD•Îe޼찳ù®Øâ uyBF» ̀ǼU:Ñš;*J_)Û¶õ7›t‡mÙáÍØ±y;Bá=¶wç&ÏfÚæA¶SdòQn+¶’”¨HŸeÜp¢YE­LîK*Ô#­+‹±Ïb‹«§µt ìrv‰Í2i…”T ¦ %u0ölV;F}©•$«$7n,ã°.sTãÖâuîh;7¸ ¼˜ÂSøåê"1Ñë©2ÕæZ€b†´‚ûš@(öµ…Algúúà ?÷}X§¸Ý¿Xm´ž592Z§|Í£hsÛ´ŽûÒx­½º7WPý¤ÕÙZe›¨Î³c5NËG_µjÇùÊÎÝP;À`aŸÛöÙ0M”º}ÎÄ`pŸ£¡Ü³‡¾ ƒÚ¼´ð_š¥¥ñõ¼f?GµÅ´È„ÇD °„7Ò±bªÂn¬;`¼%åž¿H' ˆðª»rh]´P< OuÇ·›!¥±š¼Óo¤{_ÃÅ ÿ’šfò…*% +ʾ½•ÂXm¥Ü£mª©Or¯‹¥ºŠc¸Æõö†ó,5 VÆp±Uûš¶é A§“ÜQ· +ÜÛQrož¿3Sê“Ê}sbK@‰«*ÍbãÐ Œß] … G*¶íþ¥Ù¯21wt¯f#1¶2”çjÈÝõ¹–EŠ]‘~ŕ޶éUp±·—›+îéyÞ¿0¶`|ÌYÜûñ}•óþ±‘Ó'³vç~OŸs¿ î¼ú¾P}øe1¼VÂÏò—c‡©‰º‡®½/ +º¹?¦w…«–ûhÊy“hŸÛíF–µ×Ø‘ó“6ÝâØ¹S74ö÷MAkë‘*|ÕÂÓ-!²vN±‚¼ŒŒ;PU\yŸhÄ«g¹3ŽÑ‹XGÿ¬´Lߙּ¶ˆ¯ôë8Ìô+=ZÓïEtòvEÜg¾«êw?bHý E¬i~’“êO<âV}TD|k<ëƒ,be}FLm¯{Ëqñ¹úÇ›^Œ÷å{”!ÁxÓ"p8¾]ìï¬ óµÎ8åôög<3'‰Œyæ<’±Ñi¶‰jÎIeÍi+£±Óä–QÛœ3²›³dF€‡©4ãÄ9ßf,9§äŒ9O3wƦs~Ïøu®çΕâÃï+JÄÍsåù­‡{_ï+TÄàc ËPý´ÒeH?×à û÷53ÒóÚY„¾{¢¡¯Òa˜ó0æšyîDþcö"OÒýŒÈ¥|Â2¹,Ý®MäoºûyžÙMŠ|P?.rFÝåÊÜÒäšEª{p‘§ê^^ä³fo0ò^ÝkÌÜXz–™C›ŽWa—~ñ‘ÊzþÈâôaž~ÃÆhP¿±4Ê›Ÿa¥|Hcð)Ÿe†¨úóŽ Ö»œƒ¯üQýã{ÔÃx¹¥›CGÕ/`-”s¾Çι*[Ú<Þzá.ãE¥nЪG´ÍûQÔ¹+ÙÏr,ù®Ý:ûæ¡ÚCL,M~m»U(ƒøÂ°Ø`ëÊãúµ_6æÞ¿ñÇ!ñIu í°äýÞoëQ¬ª«PÏ} ´]‘ÆMË®Cär|â°Ëºû'¥Á¿ï£omÌJ‰k£²‘ “e3ÊLÿðû'†­ßÚ~œ_{ÿ¨Ç/üøãHøÔH@iC•Gã¬pßD“¼k÷mF¾{´Ô(•3¾¢ôÎIÔ<Œtàˆ/;ݦ§3¼Ÿý(›9òc|jÉï柼 ·õ+öiìõ»~œ ¾g&ð—œ;›åo'ãŽ^C!ðsË¥C¦©`8Ì^ÃþAþ·ÛÇaÞ¡Çõ^Ô÷/òõVG«JòƒIü¯®~”ÓÅp\þšü¬ÇïûqxŒvÔª5göñVaVö¸Ö¶&QàjÅ?»J3ÕxìâT¼«cŠãl׈îƒåᚬö&y†É¹–ȃ尢úêÞEYg!å šåѱUy(2Ê«Ënõë ÚD;ôíðî Š`iÜŒQ«t¸Ù¬ª@U1ŠæU~¨¤ZV‰ÏY‰•@áÖbµÈv(—0>…uFÈÚ¦sá’¼õ#v÷Pq?nõLÿ¬Õåî§ïlަŽ+CïYE˜yíÚ<ž×ã'QIAÞŠº›êtø±“3¼‚îC<‡­Ž‡Ec"œƒk3™)I<Ž~|šýrb‡˜ž‹1¨ ©bÜžd†ˆQÙ°ÖhTNtoNÒ'‡sK%IÍñ©N›ÕËâ–bu¤–%@qÑš¬L•ª TW” +NeñÅÄBF«õ±*|Ú,ãæ¼EpI´½¾žã‡á +WÍÚ§`¯žð="Ce•÷`QuuAtÐÄömÀ Éw[°Œ®?œ‘u÷®òÙÅ1$7]Zãû½†·ÃHzrÖÇýsLÔßÚF™ÑOà³.õ8ƒ³¬ì²Þ¡ÕO‹òt†yT-±4l( +¾ Kp1Éôj݆ïsJþw30Ÿ³/&úo7¦ +Àå‘^—T ƣјØÍ­Ñç«RÓ3ßé=|ø‚› ñî{±ò_uéxHþì½¼Ò²@2¹#á??Ž'Ь«×®Tlq¥÷Ü"ÿnsÞ.±q ªS$Þç£ÿð“99°Ð°YѰ¡ráºß±{%Gp­¡Ö.oȾß3ò$Lï¸Þ,å_ÞNó}CUôûÁ毇Ðyï³ï¯'º{{D?ýc¾~_×o|@“ÛØ~TûO#›«{G}lëñM´c8<€†’¢ÑëN/¾DEÑwÀAKï·FC¶l§é²«>øžÎ%V øC̸fS@ì•%À MJþ©ha'€ô_4­Ò…¤x j8Ì|$Ú³ï‹ëžÇfK|nK „7«ñ ヨ=¨çóûªo¯úu­†ºé—Žö¥¦ŸHNƒ0T¿mñÖ¸Y ot÷¦{Zo§Í{GŽj·þ|X ä.Ìá¸ÃÖêþYG³.—á;½Ð&âviR 5/ŸêV­¦ù3ïõxo[ÿ™v;—&í· i8Žë·öh#ˆ[kO`÷8pHû>çØ/ª±&|öÈó°ý“bðÌßèc,/,‡a^|×éGƨÎ{‘ã>ïW?ÆûšïQÞÿþ®Å3z½“ál|Ϧcýâ¿ùéwßýÇ{Rúë¿ùùo~óõ¯ùÕ_ÿãWûõ¯¾þùo¾þÔ4!uÙïù<öÍ÷¢qüпúÅ7¿ùî×_ýå?ýæ»ÿùW?ÿøÍ/ÿá«ÿå_û¾æuÃÁÿæ×ßýÎŽ£kjEðû>ûï¾¹'Òÿõ›_üæ?Ø ÷‘}Ïïÿæ×_ÿö›¯÷Õ‡ïþã?þ¡køï¾ùö>îWß|ý_ý_ÿó:úg_ÿûß|õÍ/¿úïýÝ/ó‡þ»ï~õ8ÖÏßÿÿí×ßüÃøÍüûÝïü7þOæßú‡/ß{4·åo¾þõÇ{ ê÷¥}ßÅð?ÿ?ïK¿ïä?õ³ï>þ€s‚¿ù†¡õÕßýó¯¾þä(ü«ŸüWù×õ«¿úå/üdûû§_ÿÃ7¿tËûÅ¿ú›ï¾ýÕÏñÝ?ýú_ÿdøos¬²ÄÄ ^³¿Ôá´È¢¥ò/õ¿ÿÛï~bR3±”Þ¦ÖŸÿÃýŸÿ×müÝëòÅ¿ûâÿ?–/~a§ümìºÆÏtm©Ç7}ñ³ÑšWô³ñ>m>á—?ø%÷»üÓŸü¿yâX·Ë3¿íüÞÿÚ~ôÿ$/¡n':tÄÄ– ã^g“ wïñ:Úf–ŠJ¼6ì·ÿ|{a¦åM)1æk·F„oݨy5ŒMÛÉ{°" ³—Kµ"¢4r† ôež3¥Ð SòÆAdÖ;CV+Î#R¥2:Hí¤*ÞDŠ=ˆ…b*,š±íE–Éþùy«¸˜¬ …ëÛ0‹•ÄÝs;õV²D›õH·[µjíkJæÅ†–Bg©L­×¢´Ò߸Ć4-.|°˜÷ÎWE”¬²ê; ñ^‡ÆÌÈï`ç¬eJm¿¸æ|¶›1b/›Ý{£#˜3+™B‹žR¼],JMÕ †s÷(æ¦ú"­»ëÈJ›-VןrÖ0u ÚBXí³¼‘UϺ&‰Ò®úüærD wJ}uásìo“Ç¥¶øÅ$`K³Â@×­‡ï ÙÝQh¨`®5U²Ý»Á¾ð2A§½Þ™£xV€ÄUS|T+¿; DþÑÏ2=éÓ;#$¨GÇÁé%ã$¶ôç^½7›žƒö4…úUÃÌÖ•ÚxÁÔnC¯¸tÖJø´ G-Q຺lÓý¼Tä H»z‡‰Œ„t«Ôr›Ž²ÙW“ê¬6%ÕôHÁ‚°³§Þ+ífi½ ×áy|Ó»¥[h/ÛldÑ/!£{¨U•©_öÜU3®©àv–àwï¥&ëªÒþÕu8Ôœ$7Á ‘ý‰4ÞÃ.jç• %—†õkÕ= ömÕ ïý(Bâ§>G³j7,J(ÚYn†uØItNúJMK-4ãtDè[Lç¿h‡úx‹ùPL@×ë´M½F3‰Ó”iÑÐCˆ¾ +®á^Ù‚ÿtꃡ¶›ٽ暠e@QŸ-¿ƒñÐ Ôä3sã^,*·Ÿ ¾wÂäª_-çóåîp»gæ<ªÖSGŽQ¿4lÞ¸k§¹ñ¾‹Ò8~«|Tï$*M¡#i]G/7í5¢‰W¿#¬3Œ¾¼EN£™A Ò˜õ€/*ŽKž·j÷³ éFò§—>øÜ]£Ü,zÿ™¨­[|ÛLEšÆ%i¢hŸ8:STÑ)HÆ~X΃(âÿ‹užSúg,|”uQ‘^ô1B<ËÀ)?tõwæžÌ¯{ çÙ^ëe­€j!?BØæ5ËÅJ·ö—<Ãf´…•ñC™L;ã³l¨Ò*'pZ†~cÕ7í—¿È£ÙyS7ùˆÛxz“7"À¹¹£vÚî“¢THµz}¬’7ôäÔËOBn’´Þ ]å¤ xNu1­ñMz¸¨ˆØÎÁ +%Õ +†÷nØ2Î2è¹O.\d½ƒ÷‹p:S£ª0Bé÷”¡èÙ[öE†U£ÃНó4ZÓWÕßµÙ;¹ùÇ(±Ö¬'n¢6pÛb+ͦ¶—{€P¡s) žØ‰&‰9Z:70är‘ð‚˜}·Ò| HÓ·¼ÖŽ¢Õ‰R…_ÏÁ€–ëZâ´0"ö¢WkcËKf‹ò¦MJ$÷$†¸™R–íGÝó!^2Ú4ïl¤f4 v‡§| KÕn=Æ20.QÔ½½lëOù÷–î²FÝÇõ²ô9:Ï0h®æsŠoe¹¦v;zOdñ7ZŒÎ¦5P :{KƒV”dî1YZ>î þ>XR×ø²0.ÖTº­ yš°›™øv)"‡A§!ÀÛG•ݶnìÜx¿Ò@™SìÒÓx°¹¼çX>\‡‡{dÌÚÂÏZÎnqèÕá©ÿÅBY<«žFÞ3=¢e±ÛZîáIIܶ’2¬Wì +IêFÞ†¶l6g’ÿÝÈãVÉ[*ùn¯ ë˜ö˜æ”`Ø›t+ý‡ÖËœ ¡Ñ¼e£Jî¡ïoÌeÂ=µ™[kGHœ +ƒŸÅ•¨ÿ²zX£uéßg‰F< özž¶_ìG]ö ‰êî†få1›‘½™Ïö·/Ei­“|ÛAž—OÆNk¡+és]© +_]R·æï&%Jk7Ž“ô•ÅüOtHÒ7}¬V•Å|+›[C¢mµì Ë£¼”Õé¬Ý°šàúG_DÍ—!{ÓlÞV·±òŠD YùHK>€]Ä86<ËÖºš3±ÕPy\­N32E0h@­N½áõWúìt¯|#‚È'Ÿƒ›®­­0 +“VT èÕ0Œovi|Ÿ“¾dg'’ØEœÅ4uØ0×p§ˆbáoDµ“>‘à ¼ôwËÝNa^XµÀîFWªõ4KÝÌÿ–LB ¼%q 3þÁ.¶&â'6Ķp—¼IT6^[ÙÈÀÄî/š¼º£Š~öÍJœdà×c0]’ËJ¨èñ[\檩¤–N¨m°”7½™ŽGñ®X|g|Wµx +"ëU.xµiýØüN/¾»%8nmÎ*mùûü}u)Š ½ƒHßëa”«C´¹H…Þ ujjç4¢( €½ÅŽè´fPlÖh½YÉ%@jÛ/«5—½è|ßP(s£4 îRÓûÜꤌ5Ãp¹möܸòµÔ½qßôj›âNW==‚Q6Æè k ÅÈËÏd”«…Ò@¦~¸ŠÁxY$ÜâÜ—í§U^LœKmQp,o¹›x”μ\« ðy«Ó(%Õ>t1œì-ì¼{7e¿«u•6Ôâ¤yϰÁƒD=@øK/ƪ ¼ŒÕ³ÀUB‹EÌôQ—w÷ÈZÌ;ý6jÛ³.+tÈ`Ž%†5P¬?š¤Ñ#j¦,¥øåêîA  G,7Œ4©\êfº/–&5ƒUû¿øÛv;‹Ñy ೕb¡ûóžWmr¶S̶.!Ó¼Y,ñ?ÙOAK‹ÝW²ŽóŽ`Jß-€–fW>"ï¤Y£©Zf–,Â_Ú£-¶[âŽèȧþœnSÁðnY$õD¼›»$KDÔÛîÓŸ>o÷oP‹ucÁ–VtØc•¯{ŠÌ]ˆÞÈÉ!ŒÎe>çQ*|¸§w¸ai°[‘д²æ_ùñ°‡Um²Í•žCZ>zèÕ40ò8.YU„„#ö§•"ÍñP„‰A^F}UdñØM҉ʊ40¡(>!I³Âj5L§6YŠm2Œ¨Q(ÅŽÖEZŒÕ!ëRì¸ýˆãô±(½C‰"Ã6Îô™‚\Ä–ðºOSðQ¾DgÊaÂ’ñÀí²ˆ“z´¡ENÅRb¸ê”pö=Þ¦°Íh²R;‘D†~´ +Ä·JËGŸJUQÓ“ö€ˆ"‡ƒ»e‰U·íÍä%‚CI9¦>kK8e ó8¶lÊnÞ‘A´ÔE4Icg²RnfU³, +B¡@Ä™š_#âL{c÷¬±ìr³LÝì;U¦«cˆ=Ä àg:Ä +ËpQD³ì“ÅAḭ̀äR?ZÞØn짇·I‹ÝÛæ°“<îöQOk=). ÑLQ2Nkø3«³SH*Á…“a95ÃûÄŸSÉ'Vë×ZœH‹ ¬|—Ö4ܰ…Y™ï°X ±ù€ «´uf5ûˆÁrY¦ÅÎ «‘Ò€ØCê´iï”î–5£¶ðÚŠ¥b-±,~»(j•P%–µš¶Sî+eÕ=ã—k‘&êjým»Ž£É2Üoçât­(]ìW±Yj° rX3æîÆE¨æªl‹ôÄ.S¡$ê<[ìZ›ÍÝÃq»§Ë )b¹8þ“«ÒУ¤5nq]+YæŸgÙ·ˆaȱdúC¯J»ÏÁ²[1PY‘sÓÒLQ¾^1¢Óz%$ƒ²”n‰åÚRÝyÜ•ü‡D\ÒÓˆ­aÔ$˜’GH]qy\-F J>Õ‡ñ‡zœ¶œOÒº¨“…ðææˆ1Ú‘jKÝ-ÊDZô6¦v‚Ü_q+7åa…§hȱ=Ëuð­Ÿ„N!"]*@å>›W¦µn²:mzÀz½ß$jÈAz`’(ªC3÷Œ[¦Ê¿JÕÿ´'i’h·ÅÒLX”w¿-JüÅ™ºï)GÂÃ\LH⼪¡Ù,ÕÑ++ÅPÅõF,z3EqxÖ–‚Ú]×¥¼DüðXì-/Z9V;S?˜ž)¡h¹·»Ñˆv‹hE"HŠ¢È¶âœ.NOo•Þ­Ú,×ÆÃ”HÝO)\Äl +rý„e¶¢GwLg¿Õq‹U„`ÕŠWI3‘,ÈÜnjUÓi±‹°¸íe“ž}ÓC¹"·Ø&L–Ž›ué»e) ¿j”«PÅ»…À •3*Ó¸|ûm_Y,Ä'„˜«ÅTXŠ•ˆa^tAÉÕÔZcTžÚä¡2£ÚŒ𼝹8¦ñOTJþ«/)é;îí脌YýŒ¥ îןºê¾õéìPTnW¥8÷GIW2Å(lmÍòv8{¤~VöWó‡1\ÔgÈ!­lϼô¡’í^Ø:…`¨‰b FÆßQ¨Ä\*édÞLg¶i—¹Û/ó,ºN< +±Ã À¿$þj{srSWÈÎbõ4.¡x—(5ÌÊä$‹¸Jµ…󉥳A")¬Ç—lÅ’>uóá¶+¤i­5ó)Æk©á¿õ*RmSÂTQŠ×š#;">¯²òŒ +0釯dSjU·9EñûûÓMzSñy§˜CŽ¥Y-}lÌ›rqŠlÓ·Y¿°»¥¦,Z°Íkðë•‘ų6\–)Ï€Z$R„ê5A~ÎEY*0¬?Å·vš}¢ì{Ôñ¿XÓ”ÖÈz š#š×ße¤RÆV„ß0¡IªZ7嬨ƒ(Ì­õé³JL®š1>\ëŸcmWVû©²U§‘DºŒ#’`‘KåË OøAbdŸÖãogíÆæUN|7AZù¾z­ø±‘N¹çše&-LPBçç´Â- §&îÓVzãq.fTƒÝuZåV µL ª,æ‘Ú$½Zíj=lù—+߯X”ü>I\$g]l9&=å^)°1©nÐÌ(áRuY)Ûî`Ÿ(°Ý½„ßTä¯Ô”3<‰¶k›Dç2a¶¹ø2žVHy/*1q\Àn”ÔÕîWO›81ÛbJ©!ôL³s9!{½–ðé7:7k#Õ7öˆï‡gjýµW8(òÇ¿2§Jñyi¦& ÚjFßZ­¼ä¬Fê¶WqµRÐsU$„°©*`Ñ]M;Jõ¬;¹ß¨²#\#ÌÙæä æ¼j‰¬|&¶ÊFgwq£Z•FZ¹¤‹Áª*¡ÝÄ”µ†íã$Œ‘7ŒrÃÕe¤©ÌÅé”úþꓳ4‘èZ]Qv¯.G½’%à¡6+UE ?„%:ÇÓê•ü\­h8K +­Ž¡l‡,IßzÅ/óÌ”äzt÷½’ˆ‹a=vËïR ¹J>›0’ MRè§Š›, x_£jÒ¶Ö·ú¬rȈ(3\½|žªdù‘¸ å˜Q줚€{P8×¶§F‘ÂápV v‚l¤#ÁekÊ£%e4옘/ßÙ1—jÓŒ¿rEŸBTÆnV>ª —5â©R':í +)Kœ–lì‡ãFêté`"Rl%¨§lÇee]qÚB0u<tÄ@ Љ3LÇ. \ºf·Zò3ñ^K*à°¦"Å]\J'‰œ ‘O+¨*•ãqß§Ó¨SJC<Í_¶{xƒö DQêÑDþ±àœ$…UIÀäŒV«b;")b\ÖK\”F;mAþ.†¶ìyšÂ0M©¹X܇Ï1Õªâ3ûi‚¶ý4|rPÔIï^³*µðb_·—Ãå[8C§m™£PlU‚ø/¸p$¥éŸRÔ&^UtK9âi§7Ï¿ì ØDhVT:¤8 W²Û<0oýa†R;Ø8rgµ’KwºZ¿xáþ£·:Ï2àñ©P ©è8%B¼Y8%—¥’¯Ñ3²©‘Ü}ÂH|Û+ÓYoþÖàÃE*ˆ1³œNëQ¥>I6æ0ьؖ›¼)r­ è‡p©Ôɶzs´å²é·gjý­{Ж­^ÅÌëmN"cLD«æë'á~e‡ô “UÚî-\°ˆbàÅXf‰F¬Ú·Q—«y¸E¬‹Úq°(/‰%ËÔ‹›ˆ&®jBþÒ¢vŒ@½?íðlób±¾|ªMR½qšG÷Èg)ø®žËjrÅ\È¢,E9byÎÍ˰È9Uá´CN/§ÃèL‡Å²J(+it¸¨{S$A;­e(R¡3N›Ê£Ô¶C>Æä<„3bPËèÆÓ¯dΰ–ÊUi²>67_–QhÍ”1haµ ´¶Ík†®ËÓòW…^V—\‚ëg‰šÝYiª½'ª!*(b¾,ÐpZ)½Åî7ï}"›º*p²y +_…¤8S‘Ÿ¶ìÄfê«§!#¤@ý©Z*ýÅT©Ôñ’)nDÑe«×ÈÞ&l'”T‹ï£Ä +W/¦ f÷zÅH°˜4–Í»q±ªÀEVÒ½º‰ +€ðYšZc¿²JÀÈN\‚;†xת†2AbèΕßݤ Û¼/z¥BMAÉß <¨úq¤ž”¢Ac—¼!Û«›]H–«Ú™ÓV'Œ*îWSùY8D•Ùy^G(n!ÑoPãÞ=A*ÜÕuK«Ýëè¯8£;w0 +„”0fsg߸G±‹<þÇQúf±!˜CÙ¤æjdò}<6Û<`´{!K3‹¥ãÇU‰gÚ[ª’uªm.߈…9‹%a°œáô5‰¥ÀÚ˜vwM¸Ó6»¢4f`»³Ë}©„Só7ѱկVåÈBV)Ò„ÃdùµfD{™kä6WE2Tvo%KW”æì&ÿqI2çÍ–ò¾TÖ,,§2“fè3MøèqZÌ«êt·Q·« 'Þ¢²„Ô²m^dz±B(ÚÇ÷¥ 7&G"ÌSI©Ã§ö{{Té³V …­hšr×^gÊ•©¦n^k u”=Kz Âr)Í3“ˆa³©æ+źSAØæ¯¾ŠÊ£]m‡£6­[‹ëÉêbã‚ã¹7•G]©»e÷)‹¦KÌ30Òæˆ¤ÅfÑ$"$žU´Ï ½bù¡Š›wâ:lu°´O$è–è,XC~í%9/r(VUB y¦ÂWÄrp¸7EéT¡J£†3ÏÕ >øm]BX¨³MnÚiÁoÝ+—,ñÅx#‘wS„¬ÌÔ4nØRÏêLÕ»çl½õLµê*_’,iŸÌLùÊ»Ðò~¥ ÈêOI´ÞåF«äo(ÖNd!Ò˜¤¬e«˜l€ +°˜?°Å¨k5>iíE [ Is£Zw’E9WSÕ—å´/”#ÃÜx]úÕ[§Õ¦(­® -yzsbJScSï‚+þZt—$¨¼ +"ÃQŽ·I0À¥š„©ãƒTÊ%§c³,™Mèø¦ÅqYf]ì8Wüì'–Z/¦u^§ rÛ;p;NuÜÅD¥Ôª¦ëØ÷ŒD!u6Y‰½EÒê°àëpõ~IrÄÍ;§x¨È +Р׎:‰ŽetÌNkª§_[…÷²*çƒ>>¥ß?úƒ!Ãít…ÝÕ„u²Dª +€˜‡£¨ðØ·nµ7'¬ªÐG÷óaz›ÖÔÄ+µÚ—WVÓƒ¾ëMý@÷ͦÙVóïûý!÷ˆ±² bÄ#"ÙâŠZÔtÄ¡#2š¢Ïb«¨^_U™mdÝ=mŠAY= —o—èB“·¿šŠ••«"ÁÅv„ÓK4vBWcCe›oçÍW%h´S¦’:f­#Ê”¶ÍôHhè¢|Séå¥>K»=; ¢´úç÷^k „{¼VDŒàÅû.¥n.̲ ËÇYV¥¶ø—IK—øKt,;£SËU´0RdKü€©M­µ»×d¤YkÞòå•A§Ñœ¢R¸8JûbÞ—wC§¡Ä×N ãêsÓ=iÃ*ùVng1ªÿ­“ÈvnKÚ¸ Åã„ê`°®b@qÔ¤a;Ô‚å›> ¬œÍ%ƒ1hÝW¼!Ч×r‘ Õˆ&á«R’…¡=…^»QX­ÎÍ«*wâY™qóïe¨a +#Ž]][Hñ¡K£f¼ÓUYdˆÎk"°ƒm_œ Œä.~}Æ[ŸF’j*Dy‚Yt/êNáÖk¢'É‘ãça‘T^0 óËûw‡®©„èò‚ÉJS„IƒèïÔåxá’ý©bc)<‚¸iK±™Aí‹—ÍßÕ‘’Œí»YQU5EqŽÓ $WJ­äþ…Áür+/ʃp Ô]í„Pužr`Kª’Õœübt>,Lb^$îûž?ïº`œÈéU4¤àƒPåóÅ @J… c±ãÕ{"mjÛi½Ô®i\UIh‰gqYrJ%‚¯È­ÞJã¢` ‘[Cu¦ê ÙÌI2ŒãP.—e»ì³ˆÌ ºÊ}ϨÃ$_/Xóé¡z6%’:_›Ýk›Ä7ˆ¨QF®€ U(²›,-JpŬխž­W3¿B¥¼GŠHÖ ýºå£oBÛÔäqÛßlº¯Îç”úSVÃ¥•."B×úQ/Þ5/×hSÙê8W6/3GOd¯V¸oá-©Sè""ÒKqú±¶nTʪ´F êHÝMþpÑV#جSD0ôâî¶é3/Q¾´þNëb,CñD·’mW‘ÙiûÑD¤;Vvcùß6f]â¥EÜKü!væ,«i šÒ2"V)í°ƒ¥Ìð0ÍkƒWKÃJNñtÕaN´Z.ªŒts¡i|æí"˜¦P[ó² M¢—癕kQ#ª¡&³þfê¦% wÄìK„VPª—3ÔB.›öq6ƒZÙ½4i‹ÎUŒ"ÿ,Vï‚Á±mñF1ÔଟNÏl¶tXC °ôúhKàå/¯š71ËØ!RXbÙ¤¦4‹¿é zî=Q~Îå™Ô±ÕLBw'ÄmõC÷Tõû~:`ö 96¦Ke‡/W‡Â"oVéI +èÕ?ˆµ®¦âi|+M´ÞfËsTÄ™9; ®Ë‰»Ïè¦ïs¹¢²^‘~Uúq.ߌKݽü’ +‚›õJǽ«v°6}€ñ"¦ÐŸ•n')êSü}/–s²K­Öo-+SEMˆÞ¬šÃ…%·‰²ªÉ™ªC©æjJ;šX +ô—}¥Qv±—v¥ks| ¤ZL®Xp¥[Ê0šUÉ#/“§¼F‚E©cJ+^©?5*Ø=óÌ83”H)…P«UPª¯¶„ ·¥ãFZ„Ú8v©ÈÑÕfòJ"†A_Ra¤‰Ðu sô̲{wz<÷4Ji”!u)ʰi‹­Š¤µ«Ã¦ÛŠ7ë´YÔlNtNMÿ›+_u Yòœn]¼/½†(iì]¢{H +¸%n©*Éúq”ÌK5zUÙ|W,Îeá ˆrzTž~=l€ TýËz¸2estVÄ‘Ÿ¦2‚»§£ß´Üê[¯šu‡Û;íòÑìmM‘Ò968ŸÆ©»Š?6Y¼…O˜z¥+ê"-MïTÁPv;X¼)ÖÎL+=0*4t¼Ñ…¢ôë“·¢ˆuÏe§ØË„QB·ÈV„€«*Y䉮"'Z8QXßvØqZ³¨Ú,^µQ“ª2F­ˆÔ>/†ÕÕ +GxéÝrZÈü£¯ËfU—à$…´ð¦Z8”eø;ŸGÑ^÷2þ…iëJíètWgq¾¤Jó›{R´Aá6)Ê¥ZÝÓtéjÒauðÏ^únC{GÉAäq„.¬¦¤úÎ9-ÓLV‰ïHߢi„¼Á k¥ç"V/Zùà{GÛ®»µ !˜h½ÔÌ%&»Aš¤6%»#ÍL¾Èu$šÙá´üÖRc ¸‘ +ù€j'áU¡?èÚWÓjVpÊ|àÃ'ÔêÅ/fq…u½[f9ÂrFy‹ pYÌbée E4“ÑßVsáÚ¼qžõ%R±Úa‡á0Ñweûw;æ‹î ?Z tâÚB ú4›8[#Jî‹<0@/ì>nÙ,ÇYœP„EÕâvÜuÉ¢AFýìçÙkS\ +²T“4«¡ˆsXÍ…m//—˜(ª”Sïõ¡v\z ©º‡‚ƒ Iä™1JôÐÖÝÄh±Ø~PÝÜçh¡T#Ê3Ízª¬Ô¶@‹ë0 ÏLì½…H +#ªx3ƒªzXtpàM›Ðm%@N[ +¾¼Åh£_¡M„CDè£WkÆÚc“Át¯Â†¥kÄbT÷…osy)œâûÕ º»’Sª_©ÄÜ£‰*)]1ÃКKEò«§¯DfjÔ„Ÿ‡•ôɸÙQj¢Ãq-MxÛûƒùœ(딑…™@Œj68MQhCêƒ],²»_,S„ +ŽPÌ[šwÈ{³» ¬×PdœG©C%ÍZÇ\)È¥·mçjÛÖìðZJ¥¦úi­]š+òåøDö•ødóö<• ™hVää€tF4̧ñtŒÈ!!çǺF”y2ØiÅfÞ~Ôbµä¶$« +ÜGýzÅ~¼žFïl“äÞÏü³.½B–‰ÅåÛÕ»`Én Õ*D¸:«ˆÚ7ù©…Êô ÄÉ’‹¨Rø‹|}ZY‚®þúÛvÃh¿ªÁŽ´îÃî@wA=nÎÂmÍëW·æQZª›%PÈÐÍyȰÎ2,{Ù: ƒÐLÖ‰@&ËÖ™>ª•‰@VR×,dÈ…¨qºIã'l=‰@FŒm& –w5X@†ÑÖö@FêE [¯2ȸª™@vï`%Z0Èd\ë “eayȰÎ2,3€ ‹„¹'™åçGbS3€l° ²n ¿{y{ÈL¥r­êpdH¬[¦G’Vcî›d<ì7ƒ 9‹‰A&áŠsÙf™¬#ƒL†‰A¦€ìRf™Œç2 ȰÌ2+Sx"ÈPh™dëU2žoYYCi&¬â'Sá A&㈠à¯@½&ÞX0­ªF€rBU:Ñ'Y-uFUé~βÕÒ‰ “eBU•?d•ú• A†eFay#ÈjiY-çAvߨO È*sBU5”²ZËA&ã„ “eDax#ȰÎ2,3‚ ËAVig˜dUBA#‚ìý(?ø£®”£?d'™Ždž2l‚ Ä »'ì'‚¬«6 ÈŠª;\¬H¬ï +TwŒ2Å AVÀz1ñŽ2Œ’¨™ #‚¬ ö@aÓÆ-d&™ OY‰èè²BòpDÊt²‚ø uÞ[Ô·H*w@¥aDu£gÆJ°„.¦—ý‰ c&™d¥z( dÝÐdis™~Ç€ +”2=d¥n3‚L†ºw™N{"ÈŠZáY"d@ax!ÈJ-3‚¬¨Xs@uÀ Kc Èøð A†—öB†FY!h="ÈÒ0"ÈÒ²"IµAV¶ã… +вBañˆ +l€ž²¢Xÿ€ »‡ÉŒ +W{#È0N²Âb1"Èê²¼d'† AV¥<#ȰM2F™ OYQ‚a@1©L²×,+U,/¹É AF­Î„ Cè… Ã8!È$4"È$0ôDÉØd:iDécŸ2vÉ‚Œýø„ #åúDñ;&gM2m¢Ÿ²šZlŽ ³Ýø€ “በ“q@éïA¦/{ Èøµ‚Œkždidi áAVQy!ȪVÈAVéNœdµo‡M2±h'™ Å/™8³‚ŒÛ0!ÈÒ0"ÈÒ2ɧŒ²’®#‚¬ÖkFURÊ#‚, #‚¬AVÙ‹vLà‚¬ªêk@ÕmdR&y"Èdd2Œ²º•7‚ ã„ Ã0!ȪjÕ2®iB [<"ÈlL<dµm‚Ì È‚¬PQ7zÜ»ªÍq@ñí/#gB W<"ÈÒ0"ÈÒ²ªvŒA&"ôAƳžd8ôA–²4‚Œ™d`½_²Ê¦Dñ6L2ÓÄ™dÏd&Y=ÊA¦Øâˆ Ã0!ÈìˆAFˆrBU5}2´m^2˜&3ô„ ë†AÖŽ «§«bÆ2yo™®`$a d’ßyÈÌ6ÈtÒH ÓÇ> d¬#ŒÕq"uÃ@ KcȪ6À#Lò/™îÿD “âÓH CñéE “TÒH ãíŸd•èØ“@¦ÑH c2ÈÒ0½Øa Y¥’e$Õu{Èêr̲ºÔ™@V¨;Èð¹FYQÐa&Ý;‰@v{Ð3 7ñI “m$™a ™áA Ã8Èd d2< d÷ò=È0Œ2þ~È +“÷H +¨"²R÷7¬¸ØSÈø{"iëó$aœdfd: ÊH +莲"¹°@F¸÷E cÛ0ÈŠø:, #,I ã¾Í²r¬Ÿ )ᎲBåüD »/è2¬3 ËL +êxȰN2 LG¼dE‚m#¬H $Z)_2¬ ÃL »ýëOÈdd:s$é³_2~ÁD + à‘@–†‘@Æ ­O¬œíE +WdLÌÿœda Y1}$ê^²BéÁD ³û6Ⱥe$ V'•(tu™~Æ‹@&ëD Ã2Ȱ¼ dXg™,L– ëD ãR'Y9Û›@–spÅ|4ÈÒ0Ⱥ5döñ#Œ]î›@Fäu&)¶8Èý½dD™‹#, ¬[@VÁéŽ2oÖ™@†e&•”° dXg™,Lg¾då*wp&uËH ëÖ ñ*L²rŸ iydÄefÙ`IY·:¨¨l}$1õ½ dpŒ·l&¹ðOÖ™@&ËD Ó™/™¬¬HÇ|$ayȸ¶™@VÈ M²Á2Ⱥ5d÷(|Ȉp½ de;2âĬ°KÈŠôGNÆL #ð÷"qØH +K²XI•ó‘@VJîæqT-O²Á2Ⱥ5d%OA ã;_2¥'‘'’@&Ë‹@&ëD ÓgM2ýÌŒðúL #R.': dƒ¥È£ÈŠ’-#oŒ ó›@V¨5šd¥^Y©ç'dXß²«I “c9ÈË@ ëÖ "¦Œ©åM c¹ž dì%fY·Œ²n “öL #ú"‘› dÄf¡‹7Œ8ØL ãÌ7ŒøÉL CÆv&¡Hû$©Ùq"™¬ÐH KËH K£ÈÔ4È$Qü$©Íq$Ñ…8È^ãˆ$ÿAY¶Â‰@V×íA Óq¬ªðôI «t¤O26¸3Œ»þ&ÉÊš2 3€ Ë@¦‡8ȰL2ÅÉ^2ÆÎ «d/&aÖ€ŒhÝ «{yÈ*€Ý€Œð #@3Ȉl¼dX'™dÞ2YG™'€ Ë@¦\ ³¢¸@Vù—€L´„ @F4i©Ëø “º=ÉÛàѱ<ñǪ’°Oþ=Ì3L¿hâq›ßü1¬3 ËÌ“„ù‹?¦¸ÚÄ“eâÉòâaùcj¥žøcÜž7ŒØÕÌvaâÜ|óÇèuœùcb3Lü1îí›?F0læ¡«=ñǘßü±ªfñ‘?F¼ìÍÃ:óÇx“fþX•Øá“?†uæÉ2ñÇd!Ì2âÇ”¡˜ðc\Ä„ã¼7~¬nû?VUÁ<âǘßø1›*Gü˜¦Ó ?öžˆcÿ|ø1K<ðcLf#~¬#ðcõhOü¦ ?†aÂÉðÄÉ8âÇdñcžø1fÒ ?VLðcUrŽüsù„ÓB4âǘÛ_ø1Mø#~¬ªxÀÉðÄañcú{Äé¬'~ ?eÂÕVgüØë‘}øŒ£ÿõúÛ€“ŸÛÚ€Ã">Á„“U~iàÇdaLü˜>k?ÛŒ“?<áǨ™ðcD/ßø1Ü×?ÆngÂQò¢'9áǰ®Û2àÇT3áÇt ¯ë„“uÂé–è,f¯CÞ¼,þe3̶olP‚?FôõÅ£cæÉžøcEúÌOþá÷™?V"'žü1Üý7ŒýóÌS sâ)fúâ'˜ùc%áÅÁ+¢Ÿ<øc +^Lü1,3L–' ãÌ“eàÙ=ùc\×ÄãvMü1E^ü1Â=3LqÄ‘?VDSyðÇ8oæñ4fþÑ×7ŒÈÂÌÓùcd$Þü±Bjsâê™ùc|ø›?Æ›ùc|ÖÌ+¤‰_ü1®dæ)¼4ñÇøÎ7LÖ‘?&ÃÄ+šâ'þXÙë̳»5òǰ¼ùc\èÌ+ÚØkòÇÞ3äç\•ñµ^ü±"îrëü1¼—‰?Æ/þ˜Œ# ƒrœÁàdíÈÃx.¥óÇdùc´%´ŠÀ߬¬^ìü±‚#¤„çÀSÑðÈ£øPÊ@Î#4óâaœøcE¿LµNü1Œ&]C‡¦¬M,+KsÊ íÄ?FÇë€lÕ`išøcdºžü1&½‰?FÁèÄ£díÁ#ã1ñLjOü±¢ÝÚÌc®ùcåZ'þ˜æ¢'Œ¤ÉÄSBmà‘ +|òÇ|øcØrŒ‡÷â)î7òÇŠŠaþÑÉL'Œ éÄcñÇ8kâ1!Mü1EVŸü1ŒŒKšøc2<ùc%äg‚?f§uþŸûâ•X¬(€ÜùcE}/þ˜fÖ‘?VÄÊøcE0Œù«ò6Lõµgíü1F³|Ý?¦ðäÈ+â?Æ5¾øc¬Œ´íÄ#ßûä©"`àqÒÄÃzñǸì‰?VÄi­‰c*}âÇØÜNø1Í·#~¬”õ…“mÄÉ ¡Ç•so3~ ã„ã +'ü†Óú¹{MQ#~l•šø1u=ñcò*Güتò×Öñc_^ø1íÐGü;à ?Æn}±~鎓QÒéÎñÁ ø1 Ö>àÇŠä¹ü†ÍHÛ^3.Ã?¦Ó ~¬ˆU;~L]IŠ@ø1B #~ N2w#–ò„™ðcEõ¿~L¡ƒ'~ÌšÃüwvÂå…ø1E46¡Ž?VR‘4ðcø$oü˜Rù~¬EñcEÒÚü«ÇŒS†m™üÀ• Ù%~ úãä?ÆÛ=ãÇÊq}?6[õBÙÜâš+%*±&ü˜¬~¬×?&Ë ?†uÆájFü–7~ŒÕsÆ)Ý?áÇX»ßø1Y'ü– ?†á…Ã8ãÇ”MžðcXÞø1œŠ?†eÆá‹¼ñcEX–?FÊgÂQ(ö©Ñj‘£Ÿñc•:ž~ŒœÌŒ2Ž£€ù«"ÎŒø1Y\çJ¯N|ÒÇ0Nô1 }Œ?ßô1êSgú˜‚9}¬Òò¢aécUŸ‘>†åMÃ:ÓÇt'ú˜,OúXUÎs ‘E›écUÔ™>¦ÒÁ‰>Æ ™éc*BxÑÇÊy>ècœ9ÓǪúkô±*Á¨>F§ÝL«ëõ úX-˃>Æ™3}¬Â‘{ÒÇ*ª]}ŒŸ=ÓÇ(™|ÑÇ0Îô1³Œô±éĤÉ:ÑǰÌô1,oúX 9¦¤Õe}ÐÇxCßô1•oNô1]ÅD«¢Þ>écê;écª¸Ÿèc4!>écL}Œ)g¢Q¡ö¢iS2ÒÇJ´¸}¬†ú×HÓ„3ÒÇx?'ú˜º%^ô1YGú†‰>V¥¼ù ©§b¢)»<ÑÇdyÒÇ(³Ÿèc¾Oô1e Ÿô1 ’ô1õùŒô12eoú˜$'úXW÷uú˜ á/úy¼™>FÄ}¦¹öI3ÈíHSü~¤ñ•oú˜êÉ'ú˜:l&ú˜.öE³<ÛH“e¢éÌ} ýlj>¦zý‘>Vƒ¼2ÒÇêVô15”Lô1R(oú˜ÎœècU1º>GøM«*`écU^ÚHS"ùI«BCô1z6fúÍoú˜êÔ'ú1ÓÇh9xÓǪˆ(#}Œ=ÒÇÔaõ¢Y·ÖHÃ2Óǰ¼écXGú˜z&ú˜,Oú˜ÒÕ#}ÌòZ#}L Oú?{¢ñ.Lô1R /úXR““>ÆÍô1®àM3ë“>F^}¤1Ègú˜ší^ô1RÂrŒ>&åÞ>&Bü>F‚x„陎ð1Fî >Æ{0ÁǪFÝcª~ÁÇTÕ3ÀǨ àc,æ/øED|¬j6~ÀÇp2&øyÖ>Æ/øŽî+ʹð1ê#Ÿð±²­3|ŒèËSWð>F²h‚)¾0ÂÇ^qâÏ„þ—ƒ©$àSIÀSÀ“á«j\îð1Fã£[ðÃ8ÁÇdácvÄ>¦Ïác&ø†|¬¶+ácu;gøSî >ÆÔ?ÁÇxñ'øÅ_/økÿ£|d‚ñŠoÖÅ=½ö#{Lu"#{ Ë=&ãÈ“adésì14è'öUm{¬ÑIòdILªq”vGguÃÀêÆ5ÂK‡õÐ;WLúúRFìì1¦Ê‘=ÆMì1Iü‰³Ôû€+êÑcE”§'zŒÍðŒ#±>£ÇJ’Gô˜ +V&ô˜,zÌŠZžè1Y'ô˜,zLßùDQ23¡Çx 3z¬[Fô˜YGôX‘Ûè1êcè1Õðtô˜¸Fôµ…/ô˜ä&ô˜ÊâFôµ'/ôXjäQåx ÇÌò@uc ÇT’2¡Ç(öy£Ç¬NqDáUÍè±nÑcƒÕÑce Ð@ŠͺOô·tFä™Ñc*:z¡ÇdÐc²Œè1 oôXQôsDÅ5Gô–7zLñ§=&¸ =fCä‰+R«ÑcÜ=6XàÐ`uô˜êP'ôõroô˜º['ô˜Ä'ôX·Œè±n ôß0£ÇÕoôã`F±O˜ÑcÝ2¢ÇÌ:¢Ç¨}˜ÑcEoOô%Þ3z¬D'@¢Ç¤ïøBIáq@IÏqB©!õ…Ã:£Ç°Ìè1óB•Úfô˜Ê÷'ôؽ]ùzŒinF©>kB –=6X%Á'Íè1¾ñÓuŒè1 3zL–z̬#zL– =f?ò‰+’†Ñc¬·3zl° è±n ôXQ8aD‰åÏ=·zzÌ4uGôÅ{/ô¯È„“4é„cux£Ç´wœÐcT…Ìè±n™f‚´z¬\ÛŒ³ú'zÌd„FôB‰3zŒÌ÷=fºE#z,SÃz ‡tBU 7Œè1zƒÞè1³Žè1³Œè1³<ÑcøÊ3zL–=¦¿_è1e Gô†=†cþFQ¹2£Çêe?%÷Eû'ÐcXgô–=¦mÝ=&ÉÀ =6YT?ªó^è1Â÷zŒ¦ë =F˜ü‰c 4£Ç°Ìè±nÑcfÐcÜÔ =&U‘'zL%=#z¬Ö6£Ç_~¡Ç0Nè1‰4è1z¤_è1Œ#zŒ¿'ô˜x¢Ç¤µ2¢ÇÈMè1Še^è1Œz ÄÃðBÉ8¢ÇtÚˆÓ?ÑcU{Ö=FÝ„“á‰Ë£=VµŽuô˜¶è±J´}@1uÌè±´Œè±4zŒ-Þ„“hÁ=FÍ„ÓÐcñ÷ˆK›£Çˆ[ è±ùƒ=&[GÕu™ÐclœŸè1l#zLè1žè1>yBqq3z¬®ç=Ö'Þ< e„ =––=–Æ@ÙÇ'z¬ªÌ㣚hB)Þ: ÇQ¿ÑcÄ€gô˜"®z,-#zÌŒzLEœ#z¬®Ç=†qBaÑcúû‰Ã8¢Çô÷ˆÓYOônDÕ¥Îè±4 è±´zLÙò=Vq¾žè1[>ô˜ +$ôXÿ{@¥1šª¤×ô“Ù =¦‘5¢Çxé'ôQÞ'z ÛˆÓß#zL'=Ñc2Žè1 z à =Æuô˜¹ôXÿ{@™q@©JsD)¶öDQO1¡Ç¤;¢ÇªÚgô˜„[Gô®Á„#äøBÕí˜ÐcŠK‚Àr¦˜Š’žä1ÂÕy ‰<–†‘<ÖNSÌHÓ·=ÉcJŽä1 yL†'yLÆ<¦ÉcYo5’LjúNä1• ä±nÈcÝèä±)¤`Šd~‘ÇT5’ǸO䱪‚yLÆ'yŒÏÈcòøFòX7 ä±4y¬ªMc$1; ä1Õ§y W"™áAKcǤø7’ÇØ¼ÈcåØgòÅ8yLícOò1‰<¦^Ò'yŒ®¦‰È‰_qQL°ÍÁ¬±Þµ&³žWå{Áò’ ¡•üÂÏ÷P3ç:è´À¯-$à×øÕÉIjÂôyRìî­â߀ø¥¿$œDŒø…ã–¨ùe¢ŠùÅY²· ä—ý2M* ù¥y„%J ¿4?²F ä×òk‰üêlgÿ®ú +c㸧rŸ‚üâ\ö\ÅeéÆ>ÄWTVŽV_Ø=ù¥—ÿxÿ&¥€y >Á'gä{ž¿/»’Ý_wß#öŸ!”×:Ä@~QÂG¤©6Œúó ùEÁ³üjø×š1=ȯfÛY_Ä ´zvœ–Ǹ2ò ½%qÌ¡|¶•?0%¾Ä±{&~IÒ;À/þ­1Ýßþ=GÁ})mýü­.ƒö¥ëwìKÿnªÍH¬¯—Ï»êKž|¬žô%?W]ƒúbÛâ|© Lgæëòj¦|‘<š›ò¥ìRsA¾´©ÑS“_—/lñÅ¿g¾.l„{|©9{žsñ½4é]ýZx/¼§þ¦ÜL÷’—ÄÝÛ pÍß…´Wü;“½B[`/ÞVè^k¸]GÉ9HÉŽ {-¡Ð½¶t/ûø;±¼ôè7^•L÷¢ÕgŽ|œ„ +Ñ.ºfÚºeOEùˆ#:Þ‹èà-÷Ç{-¡à½¶jx/‹zÔâöØ4Yð^”˜rÇï…ØÇqñˆ:ïŠ÷ÂèËF Ç{™õ¯O‰$bÌSì}+ÞKƒ‘¤…÷¢8ÕRQŽ÷ÚJÆ{m5ð^z†¦ŒÅíÒ{sß½â½l*}Ÿ­ŠûÒáY9Ýk €ò¨ÁrêÛ²K·òärÚ‹§ôÜ:NånOÛd/^Éóm•ì%õïWµMöB9õ…/g2(f²—½â×»É^R.VSAöÂÞè úW½ôÕüL'{©¸Ô2MAöJJ"{m5È^òº² .ˆ]¯‡g +ØKûø£¥£TlýzG¤ìK´Lj>S½Ô­K&2 ^w¤E‚é%£—‹|ÃFzaqøZw$L¯û¶%ëBu™oø¬D/Ì Ïg‹x¥ÈÏcáºôÅ_â¦ë2‡‹6*® O ’íëB±à™ãºP.ÿí==¾!ׯuéKXµYðºt¢ÕMd^—z_ž©àuQîÁ”¼.F ¸· ×eãäÜ´.†R*œÖõ„cüþ÷h]è?®BëÒÃtM3ZW{=[´®~xº-Ẻ¹Ö^ ×%á= J@G Âð„ÉÊí ü­Ëº¬Kÿ&Еi] ¢zȃ֥{B-`к¬ æ¹ +­Kã8ñœ u1 )¶´®†=“Ùû­'ÞÌTTà´®F[®U©cwˆð÷ZU[÷8® ᵿ®‹Ó‡È¸.-SNEÜ×¥oÍâ, KŸ{öŸñ±P”R‰ŒBë’gé²ûÎQÀƒI°³ºì|î§¢º®Ó£Aê’@]e€º( ºßÊéÒê—X``º4mG´Koµ°ý˜ÒEéè›Ñ%ï%–qŽèºp´ž•Ð…Ÿèûn@ï¨Cµ(_³÷³Ò¹®æó|À¹.ç†s]2Â|ŸÊæ’ÏËíC‰ý0í <:™‹¯ÚÎJæ’w;«ÿsÉ̇íŒs¹;ÈId.vÖ|ËàrµÈ\/.—VõÓXW‰Ë…Õ73Fp¹U² .AO*¬2—‹ÔåEhp¹Hß~m.— “ æ"ìð¾cƒ¹¤XÌ,À\(f2½_‹?Úº÷7oŒ sÙ'½’¹°=ÐÍÍ¥+FŠ,Ð\„ +øèŒæ¢RøuÐh.‚€ì'ÍÅ£ËÖ1¡¹ðϦ„ÖÉ\ºVßd®÷õ vsɲP%/‹ËõÂ(ºÿ ,—úám3Ÿ¨\¬A(v(×;¼24˜\¯+É¥‰u\s¹´N‰jMÊd•Â=ðwN<®GÆoß8®×– Æ¥L* +3‹ëxŠ£¸ôïyÎMâ¢D“ÐFqY™æµH\\§|a ¯UÅô¢ôÕOöxNea¸n10»ÿ±ôLøþÍÉVQM+™ÁyX=·Þ飊Få‚À¥:1¯v[DiSn‚ŽßR}öšNßRçÖm¦”k\”ÏÅamXñ¹LBÞRÜèWer‚wý´ÞJ$[-ãni=£Æ·ŒÝR%®ò +Ñz£IïÄȇH½—Á³sKÕ¦úbNÜÂìö~pKÿ~û[x[—&ϳp[‘¾¶h[4&]½À¶„å;Û»X[òW;hÚµ~ eNìó6j SŒ2`[þÎ…Ú¢m½«´d§Ó•~à ֖·j±‚µEY²ê83l Òv Ûj4Þç¢m™Å¾ú­m‹Ä˜BVAÛ"ÏuÒJJëe2mK1£fó +ÖHt\gж05þ2lëò¥V°¶èù–¬£¶´éSEG&m©çBU–Úz+9 ÎÖóX}hÆl)Ä¢¡ ([ÑŽ{A¶@EŸ£0¶”ƒTª/4 Çš(ƒ°u¿6eÀ+í]|-Î1ŸøZÏaOGÆkžy.ºÖƒS°µd¡¯­zFk=^µd- ÐÖjBç!”˜¿o–¹ZÂ4êE ¬–JUa¶ÜK}ÈfÑL-Å _#¹áùjû÷"j=Ýʽ2PKQMøÁÓR"‹{<-²Ozú2P‹|»œ jé4«p¢ÖsY¦/µînÊàivô\<­é;Ú„ÓšQjê4-¸Vc,˜Öé_.ô¤i·,-ýûj}¡´NzŠF!iøyÎÒR`M;ƒàhÉæÏO‰M‡\Å5•EKzÅy¢Õ=j˜ZòI8͹÷5ÃJ¹ÁôEÐÍÒ½ 5<Øü,  J¤>KóÃèw¡gISÏEÀ³†|aŽ{±³d.­ÕhFg™ÛÑgÉYZþiÁÍâß½P³t†zsš5ØÆÍÅÌRŽó°‘Y*®Á©Ð‰Yš Ι€YTe\–  Ïó,Z–Ši/ X–̨ëý]¬,:îEÊRÕ¼fÛe1ò÷Y8Y€›aM8&ËÌ3ç¦digoéØÉ"1NàÌ)Y,T”,V@¼ ‰’ENô¸ßMÉ"[¥hQ²l=:0Y@×ξ)YpkHgJ‰qršAÉÒ+k · dµæ3_¡dUU¯©)׆dµ¨]*,Tb”ÉB!¶,Öd¤÷2$‹5 ¸ƒ€d5ê€=}àT°á­=’¥Ion HYsv&É¢@„ð`†d¡RZ,)ï$KÂßu: $ l5³É"';#KÂm7‰‘¥ÅÀ`3Œ,)ωŒÏ å!1²è:´Ž@cd‘6æQtFΑ“ÅýfdùnàÜŒ,<ìHl#‹û½ÌÈb×µ5¼t)ïŒ,•ü¾ÏóTFVƒ‹2úfd¡¯HgJË”,©DG&K +S¾a²ôÏ‹Ž°ŒÉRÔùÆ$0YQHû&KÞŽ”YL–T/¬ó>þoÆ‹>ˆO`m;(Y5//H‘øC@²PŽë.,¶Ýä­’¥íÙÓé…uH–eƒgË,ŠíîëÞ,’T[$‹T>n†d5Þ}nHVJD‘’æT%[‚dá’¨`@²€ž©Hn–ÄE2$ ï[»ÒÑŽpF‡i@²ôæ_ÆI”,œ)­àÆ)YúÝk‡MŠ2C÷CMצdI¤KbQ²L™’UÎ[,TÞÒ€daÕE˜ YR,å‘!YÍŒƒú†dÑ•|wC²ôŠÚgeHŒÞÉâ[¨xwA²¬[˜tV‚d<¶T¢A²(R·ªŸ7Š[´x4÷€di  5 YXùRKè,bqî3$‹½„Ú0’Õ¢-$ YÍ|ª +#‹çy"Kï¦æ dÑ\@yL&d¡^m±k"Ž endstream endobj 48 0 obj <>stream +ó87#KÊ`pÈ,Ú^?Óf*Rºïµ!Y(ñéË$GQ«[ÓPP²à9J‰:ÝÑLɲش-øij¢9F†GAÉRrʲr™’…›`÷ »Íˆ¶Ý‹’Êš1$S²”9³®¸ d)ÒÍ~eQ² °zŒJÉ2ë56%‹À¹öAÉÒŸ¼ˆ‹dJEؼvAÉ¢)…‰+(YÆÝ~ïJÉ"MD…QP²,qÔÆ¦dq&±ËLÉRžˆ8OP²¨q×S”,ŠžõRdJV{"'”,kÁ ¬Ñ)YJ]XÍF¦dq&¥ dá!ÉØï”,÷š«ß¢dé{غ$(YUÚ37%‹Ü-kÆd)ÛÕ)w +LYG&ûÀd‘=tKáÕªEi÷»üäµJz[‚’¥4•ÝíLÉêŒ žh"Ôª MÕœS²hJ"û˜)YÖßdƘH°õÀ¹º7>(A²¤Z„Ö Y´íXÌÑ!Y(¸%‹1àÀdYB‰™Ç1Yt90é%L–~÷ dœ,2ůóµ¦g‰m]‘AYÆ÷eNqP–>ŠNp²ôlLÏœ,Sÿ)”¬nå¦×?‹“¥ÇÜ6ÁÉ¢CíÆX!q²”еÅQ€²ð™e¼ +R,s–2*K¹Yöƒ•ÅUW}°²H`¨õ&³²Üš³-Vs-A‚•¥1›y½ÔUÞÝËÞ•…·¿òÁÊÒœ (¡²´Í¸õ•ÕÀi·YPYí(¨,–÷Šˆ+«ÑÙ©‡5q=°XÇíÂYYZìo V–` *뙾bõpÃc‘ƒ²@¬Ý“%Ÿj­%ƒ’¥Ð^zgdý†qÿÍñÿ>Diøîè«…È" Ï3*IwÞ5Gd!Ü~➦ióý›Îƒ‘¥§Å`dQäÂ?eý0…WÌ%Y*˜F–q÷ÂÈâ³´O F–â¢ÁÈj´MôYYí±ûËê<è” D–Æ[g‘¥qŸ%D ²ôÎSSí¹ª¶¢~-#²4ñc¿ˆ,lp±‘¥Wûô®çò¾3ÿ9#‹ÚŒËK¤ª$P—YˆT„9# AÙœ`dñ9G2$Kné·bÉêÝ + ‚~Õ ÛK»YXVeFVg3Y[H¤¦-:# ƒòÄÈÂþ‡‘¥QãœuL³`[0²ð"VÄ91²ÐTŒ,ÍšÁÈ’ÀœŸYŸtëYÄÔ°«øPká`dIÐÄ’Y ¹k²úðõ»²ö¿!k‰AÈê$rÚdÉsüÈÂv|²ä^YK(—=Äd™©údu\0* k÷ È’ïú…˜Y ¥ÿ²Ð2 @dIødéY)€,Ý,²œÁ¾‚ »—YšŒ‰@¬£ŽÃ»E×;ŠLÈB=~eÀ%‰"!ë;xþ'…ÿ%BQ/=™Åò_1  di/Jô-YÌ‘ì—òLŠ1Î8! ̬²8hS"dI´h¢²hÞÖ„iyÅ'éhH„,KÉšE¦XŽÇÜZ‚ըߣ²´ûf›„,‚­”÷8!‹f*%3! Q‹› d!œ–沈Ïa9Ö È¢‹¦÷àcÑfó÷‹tˆÌq2K{pbŽÇÒ¥·µã±>wì?ÿæC¡4£5D$<–òó¯U%8‹ã¸³Ç’ÒØ/e<*7Ç"v9fâcI±plæciódáÝàci<( î•‚^ +‘¶Èô«ŽÌÑ¢ +tx+•7Úz,|,T|•‚%…§lñ±¤P€XøX´V³¢ >ûṈ‚…r>wåc±/§ª6øXTªTuñ±´Á ð±Þ’ÚãK¥jÓÁÅà±–éX[ô|:ÝîDGzÅÈc;ÖÇÒ¾ó¾ƒÏ!•b¹Ãv"ŒôüÛÊ 7 +&Ä cÙÏ9ÌEÊä#=2 •:î c¡Ð +2–ûÅN­OÇ^™EÆá¡\'ca]im‰ŒÕycO³¼j븼ø+ÈXIIu [ 2–þä©mÓb^éB[Lfca›@L~§h×Cs¢±±¶ÙX[ 6õ|´s JÄò 8–XŸf)Æõ!tÆÃWL;5ë@Ëp¬òÝ®M1ìljÁ«±Ý:¬ýfÁ±ˆÊRp,6^Ä}ŽE2‚vûLÇBm޾¢…ž¸Ç=­ÍJmÖ´žðXDN  e:j‹Íºs\ÿ@À AÈ¢Älô<ùö+ÿÍéyF¥bdMmDžÇ:Ê,èX§['8Öyy×]°±X4ÝýŸ…Æ:£=4“±0ñaYk-uùP ä §¿ÌÅ"‹ÞlªPº‚ûÜö bÁº[…ba±D•¡3±Ôž%f ±øž-ˆ$mÿÍ(ÒXnç\v'@ÐÌmní%Ò94, §… ¼þX°Ö ÆÃ XXçau; …µ„LÂB¼ça)û¬¢Q®îˆF. –Šk#5…‡ûZ¬÷õ:Å Á’/N¨aÿ€i^l«§Yv0°¢C?4Ùœì:÷ýÝ¿ +)ÐWª!cä«ç‰ºÐ´¦pÞ›{E¬—æˆà^m%s¯’êÜ«÷‰¶AÇYé"Y«}¢^A/x +롳mæ•J€Åñê‰hu¯žð à•õ¯1¥îJôV Ï9íJ:–€vØ•B¤f3ëŠXò°gG¨«çŠL¹s­x +4§gЕJÑ-ïîœ+ùø“¬ ÌÕÛf‹¹R„ÚxgWý-™^€€q˜u¤£äxç³=^MñïL· +-ØVÙÐ,b•j¯Ù+ØŠ0?_(T-ï­ù!ÀV[É`+Sµd °•m–H™;°Jæ´e®•Šg£`~Q­.·ü)P+ù2Á:Ô +Ss÷·Ä‹VÂÛ+ÒJ¼z΃h¥0þX­t„Í.‰gu…-qð¬TäÌ"pVjhåešÕéÎ"K<‡wúËj eµEHV§[G-¦³‡§ÇJ_€w$8Vªõ +“Q0VX/gŠâcÆ£l—ÎÇGò`XñËšB/„¥ L\N°šÓlØÀj ‰_µÄÀW±×gµî­¥²°²¶¡ÔJ.þŠFÕû5ÇW {^¥ ‹Í€ ^%¾1e<¯‚ÝÆfR©çÈ>8¡«Ø×arªrù^æá読ä×{«®ÒK³*%‹X—8/VbW™Îx6»ŠÊŸ¾ÉUØhŸn4¸ÈUf¿ãÞxwF¶€«H!ñ¶¬Ã.ªäïM®RŸÌ{µYÉU¦ŽPçíÇc“«L¹Cy¢àĤ¹ +Å®§³«P¬"±«È kxwt + Ü®¢c¿Wp¯ëÇWÑÈy®ÂœË¬d¸ªažáP¤\4Á¸Š-OX"Wa}ÇÅrUQh²æÄ3ÚOƒ\¥§Y'8¹J#•®¢³š=åWѱÀ= p•Û®¸j+\eêý,pö zï\…_Fk \E‘Íx·ª]ÞgÜ*ÆV½¿™[%‘-}p«°ž†¤²Å¿Fôñl•4ësnïšöÁ­âj· +¥£ƒ[Õ8üé‹[¥*AæVI¤À.¸U8}«º'¸UtûkÌÜ*Ds£[ÅYÍÈ^Ô‹ò¹ît¸WOšŠ´‰lûúýÕA3EÆV­£¶ª1[µ RÙRúXÿ¶$ÚðÂ8?Fu’O‹HP2µj‰A­ÒR‚I©èÜ×~=c«0{ÐU[G™G¹¸UKÈàª-:¹ªáÍù^‹]Õ"®ŸØUh89½Ê–× zëŧex•$¾ W!´¶àUü[ñÄ ¯Òóv¼ÊÈ×½©TZŠÙŽ6Ó«Öà»SW'åZ¯ZJ†W-1àUöñsÑ«X@VàU4Ø)0¢…Bß7àUŠÛÞ-ë`VñÔ¼Šp(õ\±kYJ†W™hõAØ;S\©mVÀ«,°ôö¯¢ï Ÿ‡WIÀÎ×áUü[©© ¯ÂXƒáÀéUš¼ƒ^EGÓk ¬E¯Òc·îô*]·a1[ò<ñïÄ® +)ÐUæîƒœÖ[ %tó'‘À8JE‹F‰ôŠì'tÕ£ƒF±¬×JåwAWñX©Ãy¥š +Å ]ÕÌ#ï,ì*3«Ê%§õÝ»Š³ ×&vbw2Õ†*‡]!ºª u1{aWé+ÙibWÑÖ °ÂØUû߉]eâLN¢Äî¥"òE§nBWYGá³z¦uê¹J«mŠÏ2º +ÿQ¹ÊºÊ:¼•ñst•b‚,Ì2ºJG1.:ºŠÀ¡Ö$A¥¢TH†Q™]¥P2“ð:ªyee°«–ÙU[tv…)ª ví­è*’ÖÚdºªC¨ß…®BP'£«u•‚]Å瘱È!eŠ 2º +#ù-ºŠÅå]µ…„®Ú¢£«zävJ¥(pl•ôذ¢Âá$è]¥®uëtKè*DíN2ºJŸ…-uÀ«XõɃÕÙUëß ]Z«´»aQ°­<õ*£q¬yTYõƒ…Çö¬RÀ„·pÕ\…™mçÎ'×q[ÃÏWÑ® `U€«Ô¼O'¼s«´ò}­[ha«ÞiÃlP«Ôw©Ö¸Ä¬Òp//ú@V=Vu(ª¿åà«@dæU)ˆ|n„•v)¸:­*þ]hUK ZÕX®k«šnŠ_XUjÎéîx帿—Rþ U}Bµÿføÿ‚ªþUMs:J µ…ª’ +úm©RØf\SKÊÙ;&€Uó ¬|`§aʪWáÛíEžÃAã86²jŽno`¢Us‚"¿°®r¶c¦ñ`½¸’O;í úƒ&59¶jb¼rû1Á­šÝ+&{„;¦1?D°VÛ:•ù¼5Ô>ç†WM%àæim²Ÿƒ Mk ]%aRÕý,¦€³ `5T¡!g)£2‘«oLJVÍø¦âò%†•ZVn£õ9ÄJ¶Nv˜C¬š%q¥$ŠU3 P[hÒÐ@«ãX©LvØgÀ aõ«C·ñùÊj!¤¥­XŽÝ³þoÎ¥GD£=ŠF1áNÉÍl¥·MWJêt˜°’Šœ‰©‰õ£˜|m •p–jÐÞG©hÿ⓺­†v¾ÀsU\¶Ÿ¨ü,=žßsXìZðZK)„oQƒU*•5RI J 8¢Ig°M–{>¸y¯ÖÐw»¦¹ÃÑVlæ/û¶·ÚÊ™ðVKUg‹ õÃIc Z Db¥rX¶å¡Ø•íæ¸cЗxm¿»…|GBKêÃU fZ +¥@°E± ­¬âk(ñ•Éšên8=OËTÍG©—¡„¿·ò?~«§ +w­TåÜD,©óh^N£ø Ç=QN£¸”î^‹‰%Ñ ‚U×#gâ‰áÀ}¹2Uk©‘WáønfŠÜÀ¼¦ WX¬)÷=*€¦¯¦vVä27ëï}µû>ŽJ…¾à–Èâ•ÙÖíEP‹ºüÒImQ8,º¥X廉0†À”¯5ˆ®žôaû K±cÛ/…É…Îf)á+ËÛj(bue¹ÕŒw˜SœºXxþ®ºÑ~_Ï2¯i·?žüZsb+ˆ¥Ü›™µU-9”›b#œXíM«ëbÐ\³û›ò:U}ê>NñØg1ìnEŒž˰%ž”’ó“°›Öb7µ}/ßï!K5Ú*øU“ šøPÆmÇцƙ|yUƾ[*ˆ[@ +þN +Îhoê¾~£Kò±O_Ñç¡·Ž^\ÿ¸q +'434èúRzß\­¤¾ÖÕ¢¿@±s§FEºl~ޤØâOa7µã:d +}ÖcÍh[iÏfl%õ4ÊÖÄASÉÃ8[S†ÓZ^hK'’úÓavž#_²q[{ÂÀmMuL‰ß®/BTaªf£ŸF\"b0å«…9¤¾D·¤ZñœR[X¦¦ÈÂêlU cʇ‚Èê¢j†ŠÝ½ ¥\˜§Já)VJB…éÐ?=D$ñaöÅ®à±ÃF‡~Yã" +Ö‰¬fÝ¡dÒaÀu¼­ÅF’w!F®ùŽ”1]ž´§?;Yø­S!Æ!ZþüÝô¿‹þZÑ#e>'õë·)«ùRjÃ-†ñBéQV$Ó +#‰Ìž,n†Ð Â…jC++΃ˆ([2yåñÙÓm…ë¤ûÓËËRk'qWB_·q¸NU!¨ÎìMFxúIÔ"a©Y@'âf¾F¦SÁY{iÇFqIÅñŒžD=Y(ý°žDº9PXÛ¨×0x\¨<’n„0¦¿Å§Ôß&Õ\:ƒÈ¥ŸnûCŒ«ü†ÊtBšªé] +­Z÷ú‘&ªK-y§êaX…)“ óPÆ>ŒU¡p&ðÌÇ…ÉQã¶Àó©*dY1B.—Ž›Xµ*ý¥õ÷ÙœhßÕÛ®Û©ýÑ­pp(üMy‚vEw×qJ˜p}@í^oRÓ¦­ÊçBÓÌ9”µXA]D;e.š%ÛÎIœêÈ¥Ãm§ÄǤ½ð±,âVT„.\[ÕP{ôSߟd+êÒ(ªÝÈRâÊ^ð€÷qrDy¬YìSeï ^8"ÄÝ”zº×,qQž–î=°R,âÐÇæt¸¢*2ч_Y-OumJQ RŠùú¬ðØÑw›ýñM¾n§v¥Ï´é —=+×ÜŠ©)räÃ4ÚÞ6Ñßœ”dбU•ók÷}ªIX‹Z½ iúszwïbv鱺Þ#§-®vú ˜]%%y±ou¸¡³þ‹#ðôõà©ÆÒ®ïJ<,¸—ª]Œ +}Ö™þ©Y8è][UG4wî8ìJcP¬Àé p¼[±¯zZ•Ý>N¬ÇãôQWm§¸°¬"dÂèK†“náËR¬‚¤\ÓÃôö«ÕÉRFDŽۖTjAô’øëõZÔ…Áo;€”ð;iÐ'ýø¯”}u£¨çÔõ÷FO«˜_нÑídÓq¯Ý\ó‚Öc±CÎ5#¸ê¬ ŸË8³-fÖß¼{3Îõâ›èmBe„S”€˜gN9K­©qXMkaλ›ù³rä³í[ݛ쥙‰u‘®h/ͽ¬‹ é)°µ Ü+©ÍœNöêÔü˜µ¦T¢!¬;r©Ü"ŽT™¾îW®LÑèÙjp³|cyÊüñ” ; Ç{Xq ;…S<><”ÿ»q¬ËCÕ>Ѝ‹ž2ÛR/%[U˜oÁÖ•R{î +2Us¦À¦ˆEùš÷´Ý\‡^ í2µÇ*ŸÝ8_SÝg,¬ÇØ ¯‰/Ûeã–¦üI¬Dõü.ü¿¬.—â(Ì7ø·Í´Z¨’ P{cà¾NÝè^ÜfÊ e†âÆúRéWëŠç’ö£fëp…«(EEyRúk +Ðôjú‡T…)R.[ÞwóN”OGµZOüÅá!!½³ƒmÁð)BV‡\ý÷ç]åyö€|l'"áïuxMQy›4Ü„ˆ ˜T[Z)Á2o;“7©c!ÕM¡ÈFŰà™Bt)ÇÒéåf[)Ï ¹l³U'©rWlFõfL»J¹õ¨Ð 3ú©iQ!ZÛ&åÙü€­ªNFÙz]G›}G»Ïñøô@½qüÍáèEÛìL¬Z´iÓË£L»ãÚ„0©ÝÂò—E^¥PÆÂÞA£¿"lœÞFRO…3ìó‡1«±´)†•Ò²ŒšZh©ÄE‘<Šà¦ÊV.ÝÍ÷´øÃß·Ó˜oÊB„IUº‰Ãcé/BØ †u2.éo8Šº™¹T»ŒÐ›Ç=Òg³Ž•„0ýÆõþbMð÷“Ùþø’c êÐŽèôIçcoªéM;Õa¨Rdb&‘Û|D×÷Q׋£Åé8öø·þ'j.C»o[ojZFß‹©†Á½–bÅÉGé¸Ã‚i]ÞÛfµº”¹ù`[[»·©†[Öðl´iwƒ‚bÊfj²ŽSÔ”ø5%rÔ´}¥œ)ÂÎBÁÏ“ê&7LÐôÖ@Á¶é<“rŸ›¶UÅqÔ%þظ­ž'•ÚìÂÀ×(RâÌRnÇaï­”BúJ¡mïÛcÜèÆ CyHËq¦V7(+Â)7Ä—ššÇ®€.¢¥üš»Íl¥?ÛQw«³Yq¸Þ‰A +ç°·`j §a{)ÿÝV Ñ÷qXâ*'6½>~+ãŽ\Òš%:”ÿü[¹ÞdÉÈ)i ¼Y²kg™xê&Ä8NÙ~Raúüæà¿ |ùω)K¥¢cHÅü…;îaÍË Î¶aa¨zs”`•.åÒêÌRW§ýÍûåw÷ ›çgæÓ4•!$ƒ7.Ë%oEÍH} "¡¶Ëœº§Ü*5Ù)ËÒ_‘8ÂIK±k;í‰ÛÇ)Á÷* ²Í 3Åýûf IõÌïm ¼Ù<‡¤´›…ðZ³åŸ’ Á ›à`8 dáLòy‡›Õ+Ôþ7¶¼[±ÐèŒÖÕñzÍûX±•k;-lµws£+³¦Ì2ùmð^Ï5·sÖz·[ªÙ²,êKårõÓ†m­žHôÆ–•k¦_ÎL¢ÏÒ%å²À·¢ÿîÎ"ˆ)[ðÊ +A*1ýý[tK±%åX&ç[lVŽ8È$'H˜BæU±ïêÝ"é¸ËÊôùR%C k®°}ðĦµG¿[ýüó,»–œþÆpðvRÆMmõ<¬Þ}*¦Ë+ö7IXIƒš%å'°”˜·-•¿Ž{¢²b¾ÆrÚJ #6I„ªRKåø4hOÆhXÔš ïã +)Åg ­[Xá*<35Ð’ÌSläoAêKžÀŠ)ÇPÞÕ¸£Œ¦Î|µ(쪧¬ØI¾ê9´AWÔô„èüØv'Áì±l +¥ZÄ^L*×]ßwK [iª¡Ðb_ÃW¤Z¾^ì¤åO'X½áŸi6ü_§²eúÁƒ +ÓˆGÞ‡¿åt5;“<·¿Õµ½”çrWÜ’‚il.TØ‚ÙÆ©½âk‹q’œ næŒ)8û*¾ówçÍ™ùÄïD‹`@“zXaÙm*½JŒD(ŒI±U†Î À˜T[uñyúëµiÚd6L³Tˆ¯µÇ}ïI"·@é[P¨MÝ•=*½ôÈ`ìoÏ/öÆàmÅÕæ„Q6lL.Hãâ¼5¨¨¥0c6ZNSm¡ª•CÇ©”ê;Ç0þï!Æ,;¡íœƒ1¦ñì&Ч5÷42ÄÝ-éÏiÉDeo‚2vâíKöà°µ±”We((Š6¢ÌHûìôeóJ¯î¡B÷rLÂö@›áBU5ª6=ñä‘I‰|,…Ÿ‰†õó~ík-Þ˜†v¢C; ž^ÍL¤ïTµ‚{ +£V"ÛRÓëȤ2¾@VÒÆYàp­iQúáÆs+B®U×m‡¹Âëì'ÞP*f[ ¨fë´¤౓z~Ô´ÚÌï­üÏ¿ø¸h‰{+ £uÓb×ÁÐR1ôc)Ì7ÕqJËHùÛû Ø~ UK×N딆)ŠšK!=1¢«?É{‚%3áÆ'bߘR{<½¿fk]}b| ¶£´˜Â¶š“¹dÚ±ìF¿øGõ=ýœ6¡,™ÔƤ,U‹tê€ó—b¥„/;f±ÈPY¨˜BÝ üû·Í?Êô+Ù‹02•¢7€‰ˆ0³ÁÓÎöj¯PÀ–ï¬|àÈ&Žûš‡";?±Ð¼­ˆS‹è© ®~Úˆ'ç¿{$ß¾©zu)dŠÜý J«ò5Z ‡-VL;ìÁ£×_kB£¯W~Z¿b¬”¸Aט;¤ú^^LßÍ6ó²€’"lĹyd„7”K@ÕçN냼|=¤/+Å…åÂ+ñ ´ ‘»Ûa³Œ}m;ù Ã +ŽlBJÒi…Ëf ¿uõõ‹°O~6L¡ùjPW]‡Ö„ÙœV»Í4C>í•‚F¦ó(2`­´€î†—º•¢µ¶wïÇFè(ö@]ÜL¯<lãº!gw‹(ÍQ I6Á ÈêQiinw¿½n·ûp®·]£j«‚J¦'ìïμ6IõY«Š–=ÌÄ·Žèî»Ádú&’¥ç¶\&(ª+pQÑ‘PP*¹SSÀB} ZÐôýo§Ç\lÜ‘KWšÑžÇÆ}’ä#ìý‚'³«¥F‚%°u„øyÑ5¨/jŸÇ{éT…g™ß‹¤¾ä¿9[kÆLD=gPÊÔÀŽƒµui]cÓ¦È%‚蘅†+š‰:5³AþUpIò¤Ü«YUŽ”‹ê”Öö(*•*jü›Ä Cn «¸q| PmTA—Iy)_E¼Ö­Z,‘8R$¶Q“õ ¯ €š,´D¦MO»Ìã/7Ã^3©„0Íæ›ÉˆB4)CùãÓÉñîÈë ;ãpõ¤…óñJ´ÃS©(T“ï¶Tä‡j^T±:˜Pp_¼­YL3œA´A ,•FC²¼ôA2=ý­5ljÁe`3Õä]ܵ]\0¯k3ïxWÀ÷: ã £F—*ÚLC;gT:§Zu5$H5XQBªªãëÝ¢iú…ŽýÑ7¾­æ•šŒóýöìaŰ´Y?ÜãyÈ^…¿7íîÿÝUö°=\ÉìVÄOƒ/T<*…I8uãœ)Òiu0 +:éŒ.êbµ¯£hrzÍáa*7»•ù*µ¾xg:Ñý¾»!¨4~ÝZ³l%˜­X-j¼#¿@ëöuouâ²?üL QXèŒZA :˜ ¤;AMAÒáŠå­_yyH¥C²Õ"W5)Ê1é8ã¨ÁÞ›6ðl’šTv8ª´ãúËBKÉæd )¬§QOM¥¨ýt¤šbëé³€ª¡t;fsÕ8S7SeÕ./å¥jG\º¿Nš¡ç¦« l1™0."¼k„Ë.yr…sÌ%ÕÜc¢/íô “Zˆ_ÿ“÷~äz ‰_3ÕÆq£Öë97ÓˆTÁ_›øÔ[ °DtK++KöµM^£Ù“|ëc¾.tX9ÕåBÚÕch'í@:=?‹Â†ª=ü=ìòHÐË"ÁBZŒý›íBÇɇÁô%Åz¸BDŠôrzR§Á›RtVÓ,_’ÀE RB“{{Ž a³¸½OU›ÃæU‹̓ªC&ùªº5ªæUvó§fŒÎ‚ã1_ø–ƒ$ÜÔ«Û¢¤|`Ø”e´Ž¿÷0 Wålç¤U°Ö ªî¶bh…¥£rAÝ·\K´¾°4Ïô¤©^|8lú›—…ŽÍa£rÞÞÂÃvJ´"±mÁìíòo«0J­Ypš + +…ÁFð åÉ9“¢ŸƒÃv‚áU@‹™Ò×ÙÀïR¢ÎK¢â@±ýˆ.z*ÚéuŽò1VJNj_–]Å:“¿I[¥žÉ’nUÐ §Q…s}ó`n‹‰9¬Š‰H½TDè<0ÙÃVúäÅa;±mPòC›Mú‡œ Rh§¥ï¤,›©‡·PlÊüSÛ3 ĦçÜj˜€ +ì}z3‚îõ±)gÍjI˜eÓîÛF­Ç»ÔÎÛã`ššÃK9ìo¨yC™n+öÃ!ˆ'¶®ZñŒ;/س6PÜ ç±“gO¯¤Ò ZÝkì¶™>W¯R‡dÝÜ™TÎÊP¥à +Mô•Ð @6U>Aê`ß-BÓdˆvTÕB²iB…ƒvˆä$•&”§À ­÷k—¢„ %£Õ°5Žj B‡Ux(?ÃÍ}4Ñ„9êÄÂäµ3 ø„:t­U(±WÚþ…²ÝR‘¿T¢=§Ívãß@ö¿&ÿßÇi£š¡+Z§}IpÚ¨f`*µ ËEdº­²€ñNžËé7L$2=£”†êµ¡ùˆ0ÁÈÎü¢«<§Ÿ°vE™„ÅœÈaÇÜvÌŠËðyddµ7c¸QÀ–Ìðì®’(Ák;[x?hïÞYÕ‡[Ôj\&µØ™Ð£?v\¾èÐî]_âýE“¸xÂvk•\Ø6-p¡]ý÷ª„±‹ÿ7bØå’½,;®ã®#„Í—X-yÙ ­»¸¬NS¬Ê^U«Yõr£$X˜ŸiÁœ#šÃõYÓ…x°ÿÞ†¿aಈ½Q ¯ãÁkl¶ó>÷;¾n¯£}Ì>ŽmÑøË»Ï·Ò6Nl«Z2œa¤}UWø¤[ ÄkÜ4ÊⵎR—™EþC¹é‹¨+õv©ÂôzØx?œ¼RŒÔæNìHõ€Þ4ŸÏ_n' {–sŸÚÕX+l÷‚‘;¶ Ò$À/Œ­vëv;Õ9p5Ë +¢Ú¦ žÖµÑn§,ñÁÛ-ËA<`+ù~lµã»r ™ÃrªTÓý`¶Ð^!o'M“ÓÂøö>¼¾üÔFc1ÞPoß~oFÑhCà^A­• }w/Ì"œS5ûÞþù$zQèü| ‡¤7=Nlñ;Þæz¨ïÛ’ÇŒEòT‰™U£„b«~««Ú‡éX ô²f;œâ¤ñ0¬ÈPmñíMŠÅ15´*ý‚ÿ‡SËÿí`›=Ÿ÷ƽMrþÓ2ÌÝÖ„ã (v^L¿Ú©gvOÓJÌÑŬÎZºÊè…}¬×ÖÓyÍ*á %ôM*ÁLÔÃzuÈ !Q³–²(Á}#þh5Íb<ª×hÖÿÜ,l¬JÌ‚ŒÝ·—ˆÃ\Æ~£éÎLYó€ MŽ»êɃþ†ÊzJŽŠ“ 0Øtw¥Ä*¾ú&À)§c‘¦N°Ê: ‰qK ­AiŸé¾ó°Ó½:ôÕÞÓâ©¶äRÕ>5Ÿ›ùŸñ!/K·‹–ãA‚S_íKEÈp_oŽÃÀjxQ…”¦uJàP_Š oJÃÕ8]ÀT%úƽApóv³BÕ=™\4U˜vß’O8«ôBäMºòÔXÑ…ªYÛìê¦skBzVy¢‚CÅRìò‡³N““þ`ɘ·Ý»Ï´]øìi]üæ§ãDìA9_û¬Å 2@ ôµ©rž£®[7Üuâïºí?lo0g¢T¡WmvË¥o…T\ h[õÒ,¨ã”OÂå­å¾e~7 î$E3g>n% ûiÂ4°] ¸ÕÛÌ4ùQTÕd–Ö§à¯%ºg¿å¿9o+Á}Ù°ylœŠÕ_:Ôp®EßxÂ…OÓ éë×}¾¤,œTk­”Š‹¦ÖQ<81×›GTCÄ™kt¦zQ'^>¢cÂćO϶­|0µ”fÞ¸ ºêu÷UΣÚè¿_Ežc[¤h¯MÔ{@©¹­‚áˆ"?¨pª¹±÷]u«ÈKY™öZN‘xŠ…j^Ë +XµN3ãŵÿD…x,gží×ý4ð7_û“ §b (ÒÍwwº!T?i€$ž³Õù®ñÐT²Xn™9X¡ÓT¬$õÁ¶í³ó\ªB‰®£•8kíÉfü]JºÚi;îaán®ZcZ>F/=›_aVÇ4ÇRšKá.‡PÕfiûÝû¶E )—wóÇíq`¢§¦JkNV ÝbÉ*còêÝ´£·rÍÓš=he& Ýíʶ"¯ô Ÿl•^UµŽð‚iìÂäá + †±qº®Îíãš·Ï*Ì|O1†R—Ñ}…JK™ÆS +ÚíÏÉá¥;Z¹ÑŸÓŽ ›_‰+º ï$¬J2ýð¤²Â'¤™Û‘œ7‰‚Ÿ™U'×£'¨ìafÄP—b¿rZç=êýÙçÃvßIé5•ÔËŒÕ)ÇÅÙWþW ˆŠ÷ªšm)öe5{ÍrÜáÎÚëÙ +ÁœU!æ*¦¶äù[#=±–ìNv_J<ìãTȬj¼+41-…é{5ôNOÊàmõÊWT{wk‰˜ô>×VìÛ¶0šã¢'ÂØim¹¶úP{z$xðõÔ|=ÌõÏ0‹…@ç.ÍJ£m¸œT3³¦ÙÝÝ?ÍSZEÙT7é«yh›/§bOú„ÔÓׇ71Üt]6Û ±¹m(ÞÝ8·±Y*ÅeŒò§Cš’Ò6dn« }’-þæűr48Ì?yqæø¯U¢[6åíÛ¾×ì²_ï.££¯¯RØî]êà£õèJavP¹ sëÛãK]670ÖåTã€ìP4íÚD§.:«Ã +å<7on«ôIèFs`[àmÇãÅǽ6'S… „êýº»²n½`7¬x´ +œ¯7'8rN¯ˆÒ'\j=|ØÒÒcvú#£Â>;”ÿ\¨×qÙ[Ëá»é¥”‘ Tl«Oœ@º™«èº)Øafä +ïÍœ3k&`ÜuH^—f¼øFS*þÀ¨] ò Î™”;Q€“[Iê¥ü¿¾.åE +ñÄáGƒËæX5K½W3·îE3u„:o?Î=öy·L¹Cy¢ÜÆÎ¬,ç°7VÍìvø·Õ€´Íœ#Δ j‘f‡‘G‘tNëóƒ^|9÷vNÅ4î~vîì^Ф«èÛ£¼3í0FŸ‹Ì!Š«”ç¸÷E!,{“gŸÇk#‘*÷¢ ³á 47uN9L8”áî¤ee•ñZFL!…à­4å¹;§7MÏ ¦ÃRÌ·—Ú–§(scçL}¬ Ö¶B‡[UÈ3Ѝ>,L 8ÌzG…FV +q‡k¤÷!+ŠÉ¸&'n^ey„-úœTïä»Í›Çns–Œ=‡†}>]Ç„°Tk ¼Ø$Á*]°Í¦Ø…V^e•1ÃÔë%ã#œÃtgÌ—ì6 +jyÜfëÞ:©VqˆzÚq“j'¹R þxs*Ÿ•¨¨,ñ¢¡žäñíÒ²òäÓÃÜs¯ÉØÏ긾…Ç gw@!y¥Úé}œªL(×f~s³%7d·šhû·íÜn·5õcTJj.H3"W¡P3¼¶˜¡ª¿/ Õ[P«˜eÃ…N¨ÇÛ…+ʦ†_Âu˜.–Ê\Îé#éžäÌ¢¤´qSxë6ç$[¡¬ÅÕ·%7=ÁH´yÍÛ{É©â;}@‡„Cñm##šnvÄ—çPˆuªpú]¾ê·¿Â×å+©ç°x™Ê>€ÎÍÇ$B°ÛeDë0yMS¢œåÿR¸.Ë‘>TU6I朤æè“¤(…¾€w{ÁªÊà&¡¬µè{÷Xêãn*° BâÈÓ½=·K°–º·µ]ZJ˜åF”%%,`ÔQ‰Ê^¯ÇÞE¼0šlDZk—¤šm†:c1ÙSçX‹ãxЦçàh›X<ƒéæ|‡êp·Vfƒ|he×ÇFÕéNZÃöPr}¢Tˆ\ÔmY¬­¨ß!â·!’ ©«{m’nô·24v+ØZн¿Â^*5Ÿ—ŠR—±-ñ[·ÔÕ8ubz§ÑX)-Ô4^'¦×N“ñÔa赎“Õçá,/¢ìŠ*æ÷œQi§bÚÛD6)¯7rK¡Äó40JYø:TˆªZ×iS(… 6 + ÿAš em9•P±3ûóFz%Õn…cxÖv +u&{]JQßût'ce”h5îs+6;FÕþ:“÷f] A'½–§ùíË_^Z+ÔAîQ."¸¤µæye9Ÿ³äÓÚ+pvg÷öVú!ˆOë6wëAUGÁ=9(÷މÛü¾Ž›Q²JâEµ`Ki׆Ú%õ°^ ª|(¹=Üá…¿ù}x6؎̾õÎEY±¸"nBB‹rÔ+?/õ²£¾–b€¢nуäÖÞ<o§0³y…ÞIaÔÕ="=¸”¾ wI=ÝŒde°@:¿V>U;Óóé¸ÃKd$ƒO.e¯µ.Îj4.Ð>﵎Yƒe¦òÒJ/³{] +lâ`ÝmõqHÖIKÛæ¶VÈÚ´ë^s4Eæéå r +¦Ê”7¶Õ µ5ïc”C#CrÀ‹´7±‹B¡cïæŒb^YZ«VóS•¿8Ôê{@zóœ}§°„ÝjØ– m½¬•( žÚÃ(ÉëÚ‰Ó¾Þ¢ZqZMQ*Zz­ÀåÙ)iI}AæªzfÌóv^*v_,¼5albւêîÕÍ +ÖBû¾Eã㪻8D<üä Ï\¥2ã"^ö—‰xbÊDºÓ‚òKÄ#üUˆxš#+¯Óârýñ¤â²ˆx(…ˆ‡KÄ/O";¿EÄë$/2åCÄ“{=KAÄíñT%ú!â)¶DoÒ"â±Â/D¼¤$"ÞVƒˆ×Ÿ*HwŒ"žšJÄëÃí?o+‰ˆ—D#âñ“2܇ˆ‡ÝJ!⡌+ñ8óCÄ“Z‰x†L&âIùñ(­-D< ó +o+™ˆ—T'âé/T"žVu_"=…ˆ×ej_ˆx[ÉD¼¤:Oõ•ˆ‡ÛÆ/¯Ó‰x` O“À—ˆ§ðu%âÑm[ˆx8Ç~ˆxdi +éµñ4«}‰xR+OJ%â ¯ˆx+¥ñP>D¼N®$ñ4 U"Þw¤ŒéR%:_"žR®•ˆ§R¤JÄ“§Ó—ˆ'µñpƒ*D<\£>D<ÔDÄã¼BÄã³?DD<ÔBÄC)D¼qöÿ‚ˆ'µñ¤T"ž”/ÓáBăß]ˆxö¬üñT:^ˆxÏD¼¤$ÖV#dÏ:»ñô%¾D<=V•ˆÀ»ñ’’ˆx[ "HBÄc-þ!âé1¨D<¶›ˆ·ÿ™‰x[ "ž>¨ñ(ýùñ°ž.D¼O&â™Ñç£BÄ“R‰xR¾D@¼~^Ä£±ñØ£}€x” ž)ˆÇ™Dƒ23€ÄS§aâ™Ú/O›š +Äëà2/) ˆ·ÕâuÌ3 ؈§§¥ñ´â©@<¹—|xR+C¶Äëôbüñ¤ ö(ˆÇ õ(ˆ‡M[âQ:ôâI-@< ˆ§’µ/µñ83ñøìO¿ ñT…S€xKÈ@¼%¯3»e &t¿@<\Œ2OCJâÅ¿3/´âiWxúò_ ž© +ij‹—xII@¼­¯G1qñø% jâI©@<)_ É ÄÛé¡â¡|€xR++éÄëÏü/€x{ ^ÇÉЪñ¶’x[ žý… ÄÓÓÿâÑøU€xM Ë–O±Ï Ä#fZ€x[É@¼­Ïª ˆ‡G݈G­qâáQW€x=ÜË +ºÄ3+ì ÄãÌOC^âQ¥\€x[É@¼­OïDâéýùñ˜† O¤ +ÄÛÊâ%ÍIVÊV žnèˆÇSW€x”á ïçˆ'µñP +3?@<{ß3OJâá·õâé»U žJ+o+ˆ·ÕâÉŠ­ñôè~xzÂ+O/BâiŠþñ¤V ž&î +ÄS òÄÓaˆG4³ñú2ÕÏ@¼Þï žÙöd ^Ro«ÄSpµñô7?@<Ò∇§+«äâ¡|€x¨ˆg— Äãg~€x¬+ ¢J­º/)ˆ·EâuI‡ËˈG¬¦ñúx€xZà}x8T€xVŽÝ%gâ%%ñ¶@<í*;ÇOÃ_âÑÍ[€x[É@¼­OOSâé‰ûñHÐ ž¢UˆÏâÄc )@<ùâ)FSxjKª@<¸\?@<L Ϭ¢2o+ˆ·UâÑq•xX€x´— žÚ?+ïÍŽ8÷ÿˆ7¢™³ñF;€xW€xØö~€x<†ˆ§·ñtñ¿@<ÔÙ7 †ÂÓòåáq/ OJáá’ûððôUž¨2•‡Ç\öËÃSl°òðdÔPyx‚¿}yxŠBgž¢=•‡§ÐÈ—‡'µðð8,óð$|yx¨™‡Gä¥ðð¤|yx¤9 +Ïêÿoh;ôááAè(<<Å¥*ï_´4< •†§TixV¬ôKÃÓÀ^ixLK…†70û¥á™)E¦á ½3 åCãŠ.Óð + ?4<-b* O_¿Òð¾·ò?ÿâãB|ôCÓzQ™4<ÖÁs&±VÂx™†‡J*hx(š9 ϲ`Nò{d½\hx +tÜœ O‹¯JÃÓn¨Ððô,ØÍ4<žyA-5@…†××{œix¨…†Ç_8¢Í›'þ±Á¯àðTVRqx¶½Ó{8¼¿ŒÃSà®âð*8<Åà¾8<üÜ ¯Gâ~áð´øâðp»/8<¢‡G„õƒÃ#ÜUpx}±¶‡§8ƇGp£àð¤TÊ/‚ÃCI8<û _&|‡§ËUpxD">8< +¿ €cÆáñÿâðp/8<ÝŠÃ#,øÁá)òPqx<‡§tƇ×Y¸džBA‡GDîƒÃÓVqxtQ˜ªOߤâð?%±jÆá!žužÉ&ž]­ŒÃ“òÅáé‹VžJðXTï;Bþ›Ó5¨…_BT,Í_‡G%Þ‡‡ZpxÔñA p"êé2ÿÑ£'ž9’f^àUÁáuˆõ‡GIюã'íí?8<*¨ ”ÿpž"9_ô ‚ÃöºàðPôöžT‹^`"‘ÃCQ iÁáiB¦~iáð4cUžòefø‡g†ÿ‡‡ÝÂOi“ŠÃS¸¹âð(4ÿÅá É8¼þ¶ŠÃ3\Å/”^Áá‘¡Ë8<å ?8<"X‡§2Š +‡gFà¿8<⇇g^‡§8ç‡GNÆá)[qxTS}px:±âðô¹‡G¤öƒÃ#ÅZpxúj‡‡òÁáõðZ8<;3áðôá_^>ûÂáÑþžqxÀ*>8<®UÁáq +¯CiúÅáiðŒãþø ‡G/½Ö̇Gø³àð:t‹;áðôe¿8+4< ]…†§1ªµ¶ixÔ¡~hx¹* .ùc&žƒ/ êÂBÃc /4<&¯1~hx¨ŒAÓÂOY4<) Å…†×ÃlÑð¤Ð¬´hx¦üÒð8SÑ»EÃë‡o\ Þ/–™†GyS¦á©µ ‹ÃEÃkÀ±~ix*6ª4¼N¡t¦ái^ýÒð¬/ÓðèÄ(4<›•~ix6¼.dÐðz¸Ò.žÖ@_…‰†Çê§ÐðXÛ}hx$˜ œ_¡áÙªû‡†×u1hxÀ©>4\¡á‘ß.4<)_ž–*•†'¥Òð´ÄùÒðè•Í4¥ ¥ ……GáBfá!|Xxƒñ¶YxzF+ j¡ BCaᡞóËÂãó + OJeá :[~Yxc¾›…G­KaáiXþ²ð4?Tž†‡ÊÂS Û—…§uBeá© ¦²ð4œÞ?_ˆ‚£䥠ð¤|Qx¨…‡RPx|Ö/ +OƒŠÂïõƒÂ›ÄÂQxX¹ñX¬ãØTh;(¼¤$ôÚV…BÀP]¹ƒÖ`™…§A¶ ðæñü ðp ÿEá!JAáIù¢ðf  +oªà³ ð¤|Qx7ƌ›Gl …·…ŒÂKjX×’ëÊ(<Q°€wk²ö·@yð¶RnÇRƒ„g8„¾Ix7—§’ðÀ2XS˜“ðM°xD&á¡b³$<–vN“à³Ô&á!â $<¨Úw/ž”ƒï•Hxzš,|$<ÝÇJÂüñ!ái¶/$<…„G懄‡ZHxR* ï;ÿ'–ÿ%¶ =F!áY÷M&á1ù~Hxfþ”Ix(…„Ç™žÔBÂ#˜ZHxG?$<ËrgžB«•„ש©û%áiï_Ix| þ¸ µðP + B þ¨L£…ªðÈø|HxŠžnI%á}oæþņ”쇄§bˆJÂã¸B“ò%á¡‘ÔL“ð%áißVIxZ}Wž"¯_=Í…„G±n!áiûñ%ᡞ”J“ò%áÑ–_Hxlz o„µz!á($<*< OÛ / o\㇄§ +ÂJÂÛJ&á%Õ«°N($<Æ¥ OÛÞJ£Ž1“ðLø%á%ÕIxü¨BÂW´îdj!ᡞ”/ Íb!áë®$<œa?$¼Áë›IxŠT^RR¡ÈVƒ„§?YIxºÖ¿$<ü8 + ˜[&ám!“ð’êøê+3 ̇„gµð™„Gô®ð´Mü’ð“¨$<¢™„7Øäý’ðˆ»½BÂ#9òKÂCÌ$<Ú OÊ—„G7“ð2 ÏŽø%ádÊ$$<¹W^~ˆE£ÊíCÂÃÏ3‘ððî,$<Ã¥ü’ð@¦µu…„Ç1^³’ðh`($<…²¾$<Û¼due…„—”DÂÛª‘ðôI•„×ñ}þ%áñ=2 йBÂCùðLÍ$<”B³ùKÂcSXHxÄE + o+™„·Õ áub™„‡Û ûQHx檜Ix ¨~IxzE + ;ÚBƒô!᱇,$$¼}\ðóÛ&áÙ¾’ð4gBÂÛJ&ám5HxZŒTŽ¿$<,D + ÏÜ6æ&ám!‘ð–$<…·2 o¬üD"á!¶M³%e"á± ý%áI,$<„BÂCùðôñ•„g õLÂÓÂîCÂÛ5Dë0µÞV2 o«A³?°Ix¬Ñ?$“ð–PHx¦fu¨…„GÔîC³.ÔLÂÃ{¡ð´¬ÿððã-$iVvÀÅVžBâ„7î÷„·• ÂKªƒð¨ð) <þæ„GZ¿€ð¤TÊ„‡šAx|Tá­š²ÂÃÁ¢€ð(Š* ¼¤$^R„7V+wŠlAx”šžâü„'Ë„/õÂÓçe«ÌÂ[Jám5@xÚ[L¦ Âc <­)+Ï”_ÞV„‡3cáÁçù€ðè) eQí´ƒœÞIEdEõƒŸ×t(á~W vÀZÞÎîÓqG2èrd¯Ñ“ÌGÃûùg±ì(°ï}£ì´%"+IvÚ9 J-ÃÛSˆ‡™@vÚƒÝç]9vûýlŒ#¿9ÅŽZob‡sÜyo†ÝÄøôúÇñtrî8ÎþO"ر7¸O†áè€R\‰FGÏbûÑi¡ˆ€×óॎÞsj=&›@tþ{/z°ß…¡»± ŽAË‘NG»7„N½NÃ7HÙ~†È˜²¬nªMÝ…×,ô‚®©Åžkº¦uóÛÞ… k˜£Þ™@×,FÛ6ŬYœ@×(aîo%Ð5Õ³<ǵ tRþæé± tRþî|¯º¦øñ¾›@×”0™lœ@÷7mªÇ’¦‹@×)8¬§àzÓÚç6d`ZÙ.ºŽÿÉü94Ê…ƒ?‡Â»º†—Þi½¬ @'õï–\ÿ,”¿…‘+\feó&-‘ @×.¶¹Ï? @×°Kò’sjÉ?÷ñ?qŸÇkoháÏIÇñnþÇÙ¶ÑùsÍ¢gÐIýÛÁ=@'å8ï¶tmPÚuV]ï!èEŒ3¡åšÒÿ݉§ A§Š:¢½!ʮẠè˨ü¹ —ì{ãç°’ Øœ9ɽ =}NÉÙçê>§íÃ}?›='aô·¢çÔ¿p4å乓6{ƒç.2uwáÎÉn¯ïÆÎ‰Ò(Æw¶Ótn‰Áœc!£™£äîaÓD!Îi×î{‹ØP{3#ênnkF›Óïï´9U9Q<šas]ƒVLáGÑrg-gÖq¿Hsâ \Ž¨ÃŒ2ËõÏÂÌaAéþ7+ÒÌ› Í!s*HkÍ"?Ÿ–s[tœ6”“ø®ƒãnü¦’Àã(€Á|¶¨å×1Í.ŒN»%d¸Ü-§¨H›áÃó÷2Ìœì,ZŽB{BN–“ÚèéQÉúZõùâÊ5Š„ØúÞ¾©‰VÅàʵ~Û[¸r 4ÈiŸÇ€Ñär`;á\¹6†J¬Leqå¤NÛeº%_ÃÔø¶ÖžÔ†ot°ç,'õa& ° +/}€åP(ëIƧÌôÚ†Æz‚+÷cÄ AcYáÊéõ˜ /Á•SaÏß>ôÙ\9B ãz*WNêßöl®¶Jºë‹+G˜ãéoåʡƈiö:³û8‹3"Ÿ>G«d9=Nëžw“åˆgßd9^‹B&´K÷=7ZŽø×{Ï=ü°å=ý/´{å»Û—´0»çX޳\É`9Ô㰱Ò¾RÆðW÷ôOº§ÏYÎ>×Ù›LNúòCoÿg‘å¶’Èr[ ²œ¶õ « Æ Pž¥åÖ”ªÑ]èˆküÿû.­‚åšub?,ÆxÎkãlâb–Àr Šqž UƒíÚËm%ƒå¶`9¬bf*Œkæ–Û*X®©¬÷ºÞtœ0#sœ,·• –Ûj€åyêÖÍàÈ85ªýMˆc+qi¯ÃÍ“ì8Ї^‚†S:ö+Œ_-‡j£åPGБ²jØúu‡Èëvž´è*#¿9ZNŠ ÷-§ï6»sZr+ÓÝgØD +3Ζóý§ åĪúËÎt¤íÛæ!š·“’R[ ¸Ú—ómTSòxžÏ?-§ëzÞ7'³móZ.) -·Õ@Ë5šB¤2äx¿gEËéA`5²;iC° ë™þ™Ér[ ²œ>‡ ½ˆq +þV²œ’ çÌ*ÃÚ1ŸM–3S¡«€å0jÞaä;J-lŸwƒå˜4Ng~m—3ÅÏ÷Ý`9)|ƒå8æºï–ÓOMO ,§¨ñ«òÅŒÓX« EáÊ1@ºYû°ÓîìâÊm%så’ê\9†nÖñ–ÓŸ¼ÿ¦œ +–ã‹à|`9›ôô9X+"VÌ™,gª6…A–ãD9-²œýJ¾V"Ë‘™cz ²œ^VE‹,·•L–Kª“å:oíd<¼ÎIÅO™,ǹ!t‘´™fÁE–ÓýbžÍd9Œ¤žÙ6YŽžÛWÛÜ Æ©[×><“娛uîe7 ’,²ÜVÊ0°Ô Ë5•ÕÐ~d¹/T3m&Ë5…ÃXÙY®áoìDÈr͈Íf<·ÈršäÓê¸4á7ÂN¯²\ÃLàjû(ÕðÜQ+«‰VË–á¾X–“ÆP\9æ±fNUКèyÍÆ, \…`ÊIhÚ7d¤œ /Õ…N”S-ç (§ê.IâÉ=¯Çt''Û(N +šÜå[í“#ÿ5LN)²6,Aé‘v_¯Ê„’»b!$9„Ãòc:ˆNæÈiI2Ϲ1ršQ/­à‚"' FÓ´ž!rzÿ5TBÒx6An ·ÄàÇQ&E Ùñqí˜6dzœžvé‹×%¨¨Ùuz\;N{g =Nj·ð·Ó㤠BKAkô/xõòr‹—zž·3åô²j„W”Çáqp{í˲¾j˜ÜQíð¸ö·öy/·­&xÐX9û¬ð¸Æ¦ø<7=N +ëûEkíòÐ]¦Ç¡¢‰NãÌ[Ùj§Çñá,U3=®±¯i}Ñã^…·´¨zÜ2=n‰AkLaª© +.\SŒ hÆÇ5mÉú™T +Îs—ûl%3ä¶¹Fâ¬m8\Óʨ(vmTâãÆ?v×ði"—”‘Ûj@äšÕá¶‘ã÷´öTˆêƒéCä¤p\9)“+–!r­ÇP9”ç¸6D…Uv†ÈIµt@äôeƱ€Ã5ª_ÞV!r{L^Ç)a¯D΂Èm%Cä¶9û wÛp8í´‹Í ‘SP˜íç>N‘ÏÍ +—´ döâPüò´çÊR«>o tœ"·•L‘ÛªQäšËÍ#²*”RLƒ©µPä¤>„Šƒ"'åï9õ㸗V¬omU«dMªN‘CyœÌJ¢‰3ï˜Z¹¦$ %çA‘ÓU´T[Pä¶’)r[ Šœ^Š¡ÉdááZ£3£RälÊ}Ÿ­ +,ÔÁ¦9Dn ›!·%g?©gjP2œFÃ{«J99¥÷qª |ÚÈ)zûwm[ÈIýûUmäPNGÊaÛÌ™äæ2@UoÍÈ5ÊqfÛ9)÷¹Èé«ù™kJÓ‘I €ÜV2@n«k2™~ûýÏý5*ü¸—Xp:JÈŸ×+å;£ <ƒ Sï³eZw{Úg¡ã4t^^Õä8|+_ë4wß¶Ò]D8³ŸŸÿpœìÛíuñT ˆ’GÇÆm!Qã–Ð8eN潑q ¬×UˆqÊ;·öl`œÊ+ãÞ¼¸ë²RÁÅIìQc¦ã"VymXC¥ó×+îÒþú'Ä_óîLò`[Ø ¸¥9'ŽtÏ? þ¦¶ÖôOÖ]‡ ÏK„Lžðpwóg%ÓáþD69'»²ÑúfÃiÙŸk£á¶ÈpK 0œŒÕxs¢ß¢™Ñû];04·Ëë—츕 Á…ÛJæÂm5¸p†'£npábµ “¸pÊ»Y=@pálÍ*3-Ãö÷$ÿ-3{ÅÂ)‚ÆØ¼°p:ñ=ÇU±pÚ±ý]¾{cá´¹üÛ±]ø&{Þ©ÀjÃÑoi‹¯8ß$ +@ ·• †Ûªƒá¬šõ±,>æjâæ[e0Ý–×°ê#«Á•ÿ;KŸÃ}ÃѨþŸ‚ášõ6Î +†kÓÃŒ ÇqŠd/0œ²k ×ÔS|é`8œ¨l©î`8]~Š_ +•É>ÈpÍìIŸM†³­öýT2·S#æ"ÃI™¯SýÚepùóè³’áôJÖÁp +š§Z`¸†ßqV2!’Þ®M†#(?Cóš·´Ëï]Ép”ÚË Nñ“‹ ‡›Åù¾• giŠ#P(ö8|TE¸)Èd8T¥MŽÐÉ㟣Œè¬Ï G¦‚q6ÐpVw·…†Óøö§W4œÁ'Ú&Ãá½}·k“áhxVØ3“á¼îdŽê[ÅÉ ×Iü^³¢á°”×Þ¡áøEG8«!Úc/#:½Â/U™ƒË£¯ËƒÇ¬\8‚lÚ}/.JŸÍ…óLÅS¹p«s©ƒ gfñ+êîn+ÌÌ…#^ÒÚÆÂáOwó« §hÄßþ©X8…€ì , j$ ‡‘‘~e¦Â‘)Õ^aQáÈ÷¨D%¨p$Iç*œ¢ªo§Ë©p .”Î+T8©T¡,*‰6ÅcŽ2™ +Gy+© ÂY©¾IPáPT}\°p¤7ŽkSáô%¬¨.°päê( ÉX8ñ;^ž©ÀÂ5ª›ûµ±p Ð[©p6NÎ …c(e¨(ÜwŽñû߃ÂYNá¸*NÙMôÍ¡píÔn@áÜlË’3A…“èAÿ úꬠeD¶f¥À‘ÿ,(œfðó>ÐB˜X†Â1œÞÓ*ßÉÛ)ŠOõã‚Âi:àõ9ΓƒG´ý¦àš²¦l-NçaV8ݯísÜûú<óßT¡¡Ò…ÓÁVÍéoÖz£Âß”î|)‡vöÛ;¼26Ðo¯,…ü¦w\fßÌp©®®¨V¥LXd†úŒ}“ù?ÕDA}{mM±˜oª¬Åz0#ßÞß4â›þÍèÀ7•Þ² KÄ7eÞ.\ê øÆåq˜<êl½(uÝ=‘ Ú› +îŽ6< Euàû7gaµlj‚)¨7Ð×ãÙ¤7ñçÆµ9o“Vö럂y“85Wåüù´¦3ªcôÝî"º†GÞoM‹·)olhÿI¾]ØŸ¶ùn ­èÍ2¼›Þ·EêÜï«Ê’IIDÇщQ_l7Ù<_h[h·‹°À»áf|¿›ë&áíoź©Mø~žMuS?ÖÙÚ†ºÑ uõÊtòÔe ¤ÛÝm‘ºˆnÊÓjïWˆnàÈ­.¢›ÊQÇýÎMtS)Üß¶ãü'#Ý”Ãð¥•#Ýû}Æak+±`s6˜n\Ø]Ó­ÆéügAݨÑÌP·†ÔèêFâìoÂ]P7ÑèÉCe¨›OÔŸÔM»•㲜ºî¹rAÚ|¦Û+´@ºiMj$ˆnz©)=É@7µ§Prê<·÷ð"™À¹©%–ÂÅLsSÀ†#`n¶ÊÖ%LT´ùiÄ¥…rG™Ä%ÊÖæu?ÂÀ÷kóWá¸a~Ól)Ë‹Êi‚ãööðŠ›QÅm-ÇZË =©ŽpƒrØê{Üž(Ü €üòf `:7Á +†sZø6¡Dy½ƒÞ¦RÞ‡_æže2ltwæ@·Ñ‚îLAl}Ä`5P,ÏŸîÕl™Û¦Î_¬´Û¦ ­=mSj·óˆfn鞬·éLKɸM"–^Lܶ»Û–uaÛlIwnlÛô]s¦¶ÍU†ëÐ6·³íŒo™™mçô’„@¶” +ÚfZ1¥´Xg`Û‰;«‘Þx$E c㸶SY+?+66r¡'ì°6öO‡ÕQ@¸Š`eFµÉ×âtÛæ×\GååcÅ+nšàiçÌiàX˜6wÌËN#8§Ê‘ÑmY6‰t´£MkEå¢MÍ–íµ(åöÆxˆÂ,>›ž_ìüφ`½º Î6°¸î›Í¦4×1æF³Qê{ߕ̦% ¤‘³©!ä´Ÿï\6ª¥ +•Mè„ç1Ûf£o %ÚÍñRéáýÖ ÉF[Ùýϲ Êæ1xl?åYql°É!–9ÍŒQ熱)Ä`iâÄb#mÏ#ê0¶¦[N}DÀØþà¼2 Ʀ¹Ä†¤€±‘?c ›­€ç èßÙ7ŒMËgKUg[Ãp›~/¯ÖëÍRqÁØZóIµÀتª×Ù”ëŸÅbkQ„UXl¨„KƒÅ†B˜5Xl +ÿË>k±Ø¤^4‚ÅÖ(”~ÍÊ3Y)ÖL•YlÍ ½¹ÎJVâÊý|5“SÑ[Xl¨z‹M +õFÁb“ðwÎÂbkf±önYâ™Pl,†—Ql ï‹ûÞ(6)Zò’Ö&V+ÅÖ4\XÎÅPlÊûðLŠM•aCMÅF{×õ˜].¥AJ½[ª=Pl*˜£r± Ø”™™Qûû—ÒŽbSýóËû™Ql¨åèņÂ,6ÎTT¯ÀؤZT&hlRlÕíÿcïÝv¦É–ëºWé' kòt½ Æu!|ITÛ" “µAÁoïoŽˆX+¢²IÄ/P†u×ÿìÌúªò°3bèŸ'5x™Æ†ýÃoÐØÝàp ›8I M*ÁEcƒÔqº…ˆˆª›2ŒM"“y°Ø¸ˆ„™‚ņ‚“4±ØYNí՜Ŧ\ÚÝe [ƒ#;½b0j³4ÀŸ^ëŽG‘†LóÜ,6ÌXL2‹­{ïs³Øt&íÅbkÔåÒ“0±Ø~~³eB‹M5~DG‹Mµ{‡b1…ÅÖ »Î{³Øt¦'þ<ôÓÄÕ3ÀL‚±5åÞpùŒM¿|íih#§äÅú3Á؆ƒÞ6ŒÍ”¹Ylå¼ÅbCeá,6)ÇÓÇf±I1ãf±5kýÔ7‹­X—‹M/©}Vf±áØ´ñÛYl| ÜÉÁbkÀƒç]YlT<’Þt^}s$a¸!¼w›†+I +›Æ·L:‹M¦4›Ž2‹JÇoê,¶U4‹ÅÖ¬ÙoÅÆÈsÛ–hXW£ÁØ 6Ê.®>+ˆ •pvؤülHŽb“2'2‹úŒÇÏ´I‹|ósnJ|úêi$WþE~ÀØd‘ÿ© Dnn†±Y´ÜéÏ”ˆu«E=7ŒMy33™gM#;=ÂÆfm‡Ûµ`l”ØtoK¸`l¬»¨ƒ +›^¶û ›á~?£ÂØ |Ž c3rÊÆÖáDµVal8͇÷³5hµ +wpŌͰòÏUal¤Ù(` ›ÚØ06Îd—alt=!Ô06\ý<³cÃÑÍ[’alÐl„‹ + +S´‰ [»ÝYR`lœÉß [#rw·ckd¬½ã‚±é‹ØZ%`l•Û=7ŒÔ²žÚBcSh©cÊ +%¶p›¡œ® +c÷þ,‚¾·6 Ʀ Áe­–Œ hÆáy0k:…íîšc£zËŠ¡ŒÍjÁ þjÍ_ÐiÞç̼Ç?(³Ø¤ZœØXlT5ù Ê휷c#M:hl–ìÒÕ…ÔZ'›~÷ p86½xǦÔ(kÂc3Î4¬5ç±é£h86}‚‚c3õ·cS˜Ž²©…cÓ“nŽ¡À±QÓGî=ãØð­Sz<6Z +[»`²Y5&ÓDdëÖŠ÷ØH6î-Ý ÉF¸lúG¤eÛ´*ÿ…dÓ‚ÏÖ&dÓnó}±^=lü†d“/”D÷B²iº§3^&²ÉntñÍ‚ÈÖ ¿·èuîD¶†ž~oNdSBÖÂpdÓ1-eLXK#ƒµ‰*hòÕ¬Ü3‰MoÍR‰P?HlG¢Þ¼Œ 6W:Š ›Éé¸.²kü®æDµ…bCÅá(6”q²Í +©õY ;™Å¦’¡ ›w°Øàoõ„Xc˜Šw{¡Øh&VPl=EF±%%±¿¶(6zØg¸€o›ÆWí£Z„õÅFËjá ņˆã-Pl(‡/tˆÙv:Ý­´20DXo¯ü¤‹¥ê8 +›kÆHlz¬bÔAlf>< 5f2ˆ-©Þ9UÍ۬ߣsØ”xsØhUŸ8ll ‡m+å^,58lÖŒ?qØ }sØXa«ð‡ µpØP2‡êðobá°Á”(6zé~sØô(U›n"9ÜX³†ªŸó·Âa£åñŽuœV,ŒÄFÁ¢¡ˆ õpÈšwñ<=z ¶÷øûOÎ+ÿ"Q6{8ˆ­ô™–¹cÂVŒŽxß±1å>ó¬ 62iûˆ ås bãLŸ +ˆM*A̱H½¼šÕÒrÝßDžˆÀãí½R-¶Ãþ¶ ¡bÙ-è–S@ljºa›º±Q¸fýJÄF­Yï bCe  6”ÃmsúxV9sØ”Ÿ!Âä6Jñ`8…Îì®DÒ´}¼£EPØt?l‘¶÷üÓ¯|Z”§£V$SØé<ì·Naã8š7…MJÓJ¬PØš¥ùîMa#ˆ:f°I±¸pư)@cqæÀ°5€ +W«©Í”¹@2†EÞȸ¶nÞM¿†ÕT¢örHÚ°¡ÒN+0lRxè†MŠ›2†"v¶ac»K_´À°¡÷U1lp†­¿åÙ6=ßtf(6FtìNa“go:” +Û2„m‹n Ç–É`«µ'Ï™ÁF#Õ+ø/R± ~lûc e»9p2m‹`³Ÿó±&É6^¢&ØPñ¶€ E« `“bß=ØØöym¢X§ì•¶y`£#©U¬$[ç½=¬Å{³ Ëé¾·°%%9¶6ýɃZ ÕØYPy™lô­ ÑÉ:ކà˜ú Á¶…Œ`Kªs03^DZl N´„ ›Î4Y0ØÜñpÆӾЊó2ƒ­Ñ·Ý®õB +7ŒÀÁ`S˜E{a°Æz 6¶wXƒÁFVä¹ +aCmNXÀ#…`ð¢°5š>ÍV)lp‰K† e:Ñó9+‡Më‰o9@l +ûZÖ(@lï±òWÎÛÓMš…Ã6ÕüÞ¶#:Єíð&X…Ávœ^6Fš«oÛá´ÀFìÔ‡e­ÆtÖéC9´™#šD¼’£m´š²WW¯`µÛƒå‹«vxœ«vë±™©jÊå[hСj´y†ù"3¬ ©âŒT#Ž=æ"ªÝQÉø4ê¡OMÖ||SýÁ’ÇNSÛBB(mÑYj÷ã­f‘¦D°á'I ðHGÑûÆn?´âߢæÚB¨ÝÞø'Àh*;g¯ü4ÝèNÝC¨ZôS²øiK)ü4Sµr ~šìî”v.šºàP9•ñi"EÍ,FÙÀ‚§Þn©°ÓTÍÂ<ëì4zÙ{wSºÏ«ˆ•ZžLNSX*rœ¦þ°öÇœ›¦#Ìš°ig4¦lšò\ ‚švÜ~‹24íðö,KT<Ž¡9i[HÄ´%0íðF^‹—¦R-j¶2.M_ÀpRŽKS Šh1 -MËæ KC¼ŸÍJ;nЕÆ/kW%¥Ñ¿Vïm€Òæ´–y‹“¶„ŒI[bPÒ°h÷âÛãò®ÑÅpF)ïõXÏ_½GÁHSÃQ&ÂÌHP›ÒÀ`¤A oc£ÏTŽÅgBû;Z‡*óˆÛNœ¶•üz/uÒZ¿·s"ÕÑ“¾Kˆ4k.DEˆ#ÒÔ®Ö¬Ò!9Ú2 ÍÚywÈg‘7.|4­ímY‡ ÊÜ` ; Mñûçl³ÒL¡ÎË;Ƥ™r…r‡Æ;u-@ +0Ã@¤¡˜/#!ÒHO?×"¤éßd5!M«çO¯|4y[,|4m³l¾ >ýЬõNâ£Iµ|gðѤœ´! >;/´ F_Bò„H+ +eèœxDenÒ¬›¥òjHS¶ò„ÁGSTܼ"›¦m +÷lñѤX‹Ùà£%%ñÑL½îÍGÓ5µTBðÑè)ÂПùhø~†u¬óž‡^†»ðhêÍK\ðhR½žÍñhô‘žÎ=³½€FöqW:šD/s<šsžc yœðh´]!3x4%Ò¼¯–ãÑä­1TÆ£I5ÿ_àѤLÜGG“báÅŒGCõæ€ÐÑ8±9P¿+)÷’JóAí £5œDæ½>…Ä`¦£íゎ֘ÅZ€ÏèN„lÃÑš¢ê$+üy:ï]‚|€1%ÃѶp4mÌ¢,êmØÑg:š8v×qºVØN–”ÄGÛjÒxº 爴¶ò ‘†hÝ–’Ö¦T$M›`ª=#MšÕ$ ¥µÍHC ™iút{‹ƒ‘Öèð~^~¦Ý¹9Â3$m¹{ÖaçÇ}fÁHÛJf¤m5iö憤iŸLš%3ÒäN2HF¨G}žÅHS,ÚzNdFšB¼n F‘TÌh±ÏÙJf¤™ê¾&i¸CÙž#­©P‚zÓÌH“j­#‚‘&Åz9;# ÔXf¤IõnsIC¡Es@Ò¬HÇ­-Hšn¥•d:$MWqxØ—ìÒ"-´EH#Õ~0ž;ù¬iµ&U!¤1ýÒr}'æIG#¤m!Ò–º +%²žwA>Ó8xçõ[!¤ñÈѦj'l3é ¤)œKÁ`A¤I}šÑ,ðrXMóB¤q"/@F¤¡öÀŸa€8.‹¦/Dš2@‘¦¯æg +‘F9¶GG¤-¡ ÒL¹;,†k“ψ©Y!t"¤É©y~¦Þ¶Š·/@ÕPd=3!¶²ôL Bš†žBš~‚­ø2!MÇÙÀê„4B“ôô(­eDujÖ‡2Žká" DÚV2"-©ŽHÃuƒ 6iüÍç‹Fºýò†–¤U#Úé! …ŽÆ™†j¹bG¤ñYÞÜ匶•¹gBµ<ðÒAŒJw³„²•„l%Ò’ê„´¾2KA>³æ´Y±EÙíƒw¨äà5ƒFësÖM™†Š'"Ò(A£¶3i¬4q 8"-„BH[bÒd¿cé±z³ªtH锤aíöoí0..>š)O48g©ÁG£é £qðq´/±K’ùhíæÚࣩ«vÏÀ£iéM¿»LGÓòš1;àh*~¥«fB£É¯ é Èh·‘ƒwvª#no¿,šº¹² sM»%³À8m жĀ¢Õ Ï™hÓ¹ ‰¦’¦îÍÉ‘SE5D{…Že\ú¿qÚ_þþŸ~ÿwþýßÿÕÏ ö§þ¿ÃM›uÔÔú!ÀiR.U +û½I#ŽŸOÊÑ>vL°Óæ‡0÷ùÛÔ²">’ZÇo?O½ÚS µ"çµéiSZõ⛪“yE=‰¤Ð&ÚŽÑÿ’ïñóä ³ƒ¨œš8n;‚Ú¤9ÎåÇBmÊ;-Û茸Ë4⌎û˜Áw*{©ˆû蛣6•œ?‹ç)›±–ƒðgFŸÚZ¨Ç‚ +Ñ…—š×½Yjj΃ueÞnÂÓ®>•ýÐÔšz§`s§¦ZžŸ¹Õxj?sm·Ãœ§Ö,©,%ÕšQ¤:QM&µãBq¤š¼†Ã>+л¢’Š<µh|¾\Ì?sÕ¼ ú®mÅþoÎ,ŠG™n”¢‰±-åÞ ¯­ +Wi ÷n!¼Ÿgκt*ðÕøÁc³ÕÄXU™ü>J›ž“Ï ®6Îíp¦ZG§VTXq·ƒ{Q¿ç°ÇR +qd”hž++TR”R`wΨ^’rüÜmS²fÉûSê唵sÙRßÖ8kKyz"­mõ¶Þúá–VÓL¯ùH!¿OW\6»²ÝÛ9®ã˜ô˜œ¶Á^B¹#!^²äd´wñr]™š—´pWïyôf4Íkjý•mª_«<ÍÚ#MÚ ÒÍ­m(Ûl·Åþ÷q8_”,Õ¨-¿äêL“0†«Å€Fƒ§Ëz«K±ñx\6` 1R«œ]õüö–òÌ …É…Êo)cx­îà11 ‚@ãÖÍOCÏ”µ!â§³Å÷¥.Fš5U;©ÚF­<¤P•Ç™|y/¾GŸ”ò¦Ò‡ab€£[ßãë·ehiÆ™ýNþÝ.nœ&=4·7öMʳ¡m[Ufípôpnó%ŠÐ¢®ÝŸ¤ØâO0†ò8®ƒÑgV–·•ûØè¶¤vc·MúÁÉ*t]o›j,ª\²:Q­>‰äŸÖàÐ.Í<Ÿë’ b~]¿m’P:Tà"m5µýõNŽ#¤0ÕâL3_"ømRY£é8æWí×t!é¦Y _€jâQ ©¥¥Ò=OÊ©x2 +O±ò"ê£%!ðmo;|À`)Œϰ2NͳƒÕ¬·™êܬD‡åø"¹º}ªUT'›CUÑz¥ÎÔ™P? o”†_ê u"ç×Èt(ØËK+gEÀÛŽh>'•  +x^)*XAÑÚfPºy~©<’ÞŸ +A[ ÞâÃ?êg“z¢½M?ýáÀã7ä£¼Ä úsù—2éôçj‹jͤºÄCýÜY…Q¢©ö*ì’BáLÀ¨3÷¡g›Þ·iAìCÎh5ËœýØø67øÖ{‰ëäPÉëx?ÿqȤ}Ý×Vø›êÛÚÛHÇ)-Ñž¸ç“…×£_ÖR‡š®iš9†ÒçÌú·å1ô‹:Ì×P8óãe~û8åÍe§ÒnŽTæVí†h[ÕP{ôC߇ÔLfEµYJ\Ù“¹z§çm“*­Ìµ¾eð¢UDÜM©6~,tŠÂÓòx-°"R¼M*‘ T®¬ u‡&t)ŠOXê>vÌjT¤ï6ûíšZìÂ}«3‰ lö¬œs+v¦ü„#¦Ñö²éˆZ襤n!Ig­E-± iúsžc+œ©æ_ ë8žµ{Ô_ ³ØVžÔ6©óãM·õ»Í׃¬Å»Vñ¡Äc` îPÙ^)¢Ï:ö?™…ƒÞ¶U%عsŸ_i%M:›%tƳûª‡Ùýöq†~uU…q¨ù"«ˆóYä.‰‡: j$åÔ²|àòЯ¦žŽáú٠ͤbJÑKâ¯×cå_RXfÛ1·)Ñêí cf'5 æWR +‹»h—í˜ÓüK±7ú¶l:îñ›K¿n=[¹7¿m«‡ãi4|þ,㬵4“°þæÕ›uD]ü6¾ oÓ1|„SlùC›êA3- 4IUùÛšJ¦»:´½g-ÌyW³žÔ¬ùlûVsãÛ43Ùºèçú€oÓÜkë"V+wVTø¶­*­†{u÷Ö$\S*QŒÖ9eŠ£ØB_VqÁšåPÛX&Z€h¾±<0cð5œÉ«ãóдÛNáP¸“å¯c7Nô-Tí£ˆº 3µŽ¤ä‘`©ZÒ[‡Ç p™V¨Þ,Eû®À¦ˆ…oSH‘ÝÜ4¡ùNôKÛ³Ïcø¶I_ŸàÀøÖ’ˆKü§Ñ™h+‘aÝ…`uùñw)Ž¢'‰~€ =šiµP% ÍYðÛm8½­PÚ& ·L™¡8ÿ@*vZùÓ6 åø¸ÂU”"w ”Eqûù{?#~Œöï²ÅH9m¨¬u¥z«ÙÅù,›­Ø»L#¹M՜ٶàñ«ÿ‰í¹Jfò쇉ډHøySä“b“Fø`¤÷¢ÊÒJ*Õ¦è×Ò[«›‚ÛN{Ët›êШ‹†aÖ+“–l +½‚‚ÔÿRJ›Q~G0Ý´«ÁZ®G…âßOYukÛ¤›ñ°UÚé(Ä".ñ~yy´?œtI×ô ‡x4²œtî³3é`£K¥!–G}<ö>‡´›T"Ä+ˆ¼ŠÎ<=^a{ZïêIÒ™ÑôIê¡p†}^ã0fUÂÚ뮵úÕG/­)’¬4Ú€àÆ›€t7ѪõçÛiÌ7e±Ý¤Ê oâ°ÃXúKí6ÇõQvC„'ˆÎ™W³ã¸GúlÖ±í¦_À¸>·ï¤ižÏ’c *‰èôÕ A•¾“éM=ª'dS x&Á6_‹®¯£Nœ¸zJ,öäÿ–Ó&ÌŸ¡ÍiëMíà é;ÒÊC_þm)vQ†AªÒqîOW€Éb‚[i›é¶ÕqX'yœ6Óé—O6Û¸ñ¼FÝê­(‹µ6«RW¢‡ ³%2$ƒ4>òy§ÿK©Ç–B.(Zzë [L7©,«õÕl=%~’F5FV2ê22…b›Ôû8YÅI(©%Ë»¥p"Ä»T-žõxv›ÙÙôô·“ zÛ•Š)³)ÝÇ)jjñëk5ÙW*â·šy(øyx؃qKAÓKo#Û&%Ê–2ûFºmUnÇÃ#ªÝ’f²u)ÌÁt«m!ݤÞÜ8©ŸnÇÑi…[)…ô•J w—åîãeзåõ~¶sªåƒ_x£¬çñX´L³¶]ùؽÝÞrg+ϱ;/U›I\êz'ªfYnoL=)í+½é÷q´ ¾lû«f+*!œ+@…¦h9‰Ž‰ó_²úwk§zcne=udD×qòª){Ãç7ÿ\àÓNLYê_-‚‰Tº"¢hÏq`¦kþfk|”²¸nö¾_–`•>i ?}“¢@Ž”ëáW>›ë¦ïæg^Ö°j*Ö¬yD9Ë%‡2鮿‘På.¾ù Ã';maÎÛR6„“–b×vú·Ž“mä!p‚vÓý3¼èi~6òiÒ*“$À´Þl‘CºÝ¤H¥-ÿž¶ðnd§Aw›gÓÔçë FêýŠ…Fg<°â¡€Gsãuûbz)2WG¯ˆ¤>Ö‰gÐ{]?éé>¾kƒ÷x®¹­˜³pÅÝRÍ–eQ,—ëé>lKaõ¤­tlYQ¹fúåÌ$ú,†(ùï,ð­ðÁ°«³`o¬+Õ½A*´7…"ì[ܥؒr­~óI4oã “¤xèÏÅ€ç¦yUì»NÂ÷q§ÛTìCHUEI(Ϲ†U.D•u;ü³7VÊ móßô ý<Fºª…d>Y,&³Oó1û$):Øz7ÜAÃíñ_=z­NËV2ÿMqèao§æýßï!¶©[¤WK0ôÿM*iA©Ê£p˜%㘠àP°øo¨;ŠâzB/·ø7)®Q"ÁB¢Cƒ¯æQz¾éúø«7Ièøû"”¾Ê/ñÁÄ¡xŠÍê2j—­KÂZG1"§(ùøª§…«xñd<ä†V ]Qm.%)f]¤~oþÛqxžY߃޸ü$zôç#¿pûâD;Ù ÀIµQÂÚ)ßG´…8,D½wýØnqât P–|n»“Ÿ¡%&éËÎüÈZ e!à¤ÚuWlŸ¨œ'Ziê-a±¯aØbM wP{¨H]î´‚ËÄ/oþ¿”-ãã4xäõ±·ü %{³3×¶ªIUó)ÏA>(X +¦±¹8¬¼çæ#°¥´*9¹]äu3î xþôÇFœƒþ+·EN*¾¢‰ÚPé›3¡Çoù›'•QÏ>Oï”íJ¤°'C9¯†²B$I>•å–ê[<„”?V©͉Òç†ÀýìùÅ>¼­tÛÁAC´EùJå‚9. *òÎFËiª-T5¢ÚˆqXÕö{,Žaü×aà,;ÑÂ]ä8=P×5§/¥ü…#Cüxïþcz2Q|ÇÒòø´Ukc)6–#ŠK™‘öÙéËæ¶¹ÇC(„î•§§ ƒ:,"¨ª!¤]ÓóÈ$e*Æ' u£ÆY3,ùbnaà4´Üí©43‘øù,ú>j°ÇµÙ–ê˜ægBe|Áþ¬Ô»ì ÍsÜRv²U«®Ë>Žf'ÿI(pœx¦¤– òl–TƒwÐÊ…Õn3oæûVþé>.„H•„Ѻiaà…Ÿšºé ×,¸Ê7å8¥e·Þ…½ •¥+…Y·k‰šK!=1–k¦^,™ 7ûÖôñ4®‰JtõÍ»À#¥ÅÛê[ë’iCIJ‘–ÔˆüeJühFYL8fe©Z¥cRÐ_Šy yŒN;fqáPµ2JMÁþ=í‰WzU‚¦×öÒ|´;z„˜Ùá‘Ë»=`a_Ú–ð†›°4©h…=ž°‰ý²g’U4}³Ù$· ‡S(ß¾©6K8™"y¯ãÌ¿Fåâ°ÕÊ‚Ãi‹=˜c´gQ¨•€~ŠÖ:¶TU7Ö+ñXñ:ÝNßÍvÍ›òMð4‡-¢ø-^¤â³ÂËÓDdÙ'QIDÑ‹XâG±]7­Ûa?ÓŒ}í;ù 9Nßëæë/Óåb¯«¯7ž`„}ò±Épx¿å„Ú021Çóíi!\@7lCïE†Óyæ2ÐFZyÝ óÞÞTÈ ›÷ûÚh"0“ÓüÊ#¡}>O½¬pt?ÓYx¸ÉÊE;(她Ýýrãîíã9A9Þ0™«‚§'ìçΟ‚!œF9ˆa‘ô^fz%‡¦ ˆßžíV‹'Í›ZË +b¯ýE,âØÄÎh“f·Â×xLë€ åí"!£ýÊgêÄÃ8(9Êtˆ(ƒ?È2`ڙć=(ƒÏW±E“Ó‰f‡Â±­áHàt-ÏY·ÍV°¶±À97PŽ,ëã®SËcƒ~¦"Ð(øžÜ¤çÚT9ý8v¤˜)Z¢_ÒmÏ6^µº;<øºÈr\+íÉøíL†ºN•:¬äUßý1iæh¡ÁÏò_/ýălWö0k¤þ—%”?m戀bá£å‹Æo§·Ç˜‰‰Š½f&ˆ{Ç&d$½‡ÑuUi<ž­ôñg’{û˜­yY·ð((Fݰtž™'Ô›ŸªE€Yúú#+Ñ`OŒ×–žlê:Âß}ûˆ‡–£Ö>O}´°=æ§eôƆ§ð­|²Ø¹õèˬ»ŒéqOT×Ó&E6F)8Û¤˜›Ž.ŒŸcù!z¨¿¤–¨!ûþv·áá>ø_¹¶å:IÀqùáÍÑÏ¢›óC.Y̨ˆ<6qŽžDöùÍ {0ÈãÌ9EŽn3ĆÎSÑ fÔ9 âJ21ã€ÓìeNÆž¸sRÙy©.‚ë¯Nn4V»1"…õ4ÊBÏ1è +|N¸5Üzú,ès(ÝŽÙü¹Ë+YñA ;——÷±†¶”UÃ-'r%څ譥݂O˜$Êån2Ó—õ±‰Â´ÃvLzI¬·ôǦ/F\(öX²´sÜ$ºæyÂw^¢Cë=þ£kÖUÚ| Þ¤ZŸ‡ÙYk|óÕÈJ¸^±2½†ZÙk"3Ú^‰Ù Žÿ¬§èHªSU©Å½^sóèH2³>Å‚EÂá°5ÉõCòû4ÍìGÇ"ŽâÁÃëÉô –fï*xtØ ®0v``W´•e)T®fkJûwÛ<ºªêÍ7å Eã\ØÊL‰º#© ´*ÃfŸ÷E¡úI +©R)Ëâ¯Õ­†Ò$$h!QhÕ’óòM³žÙÒi:¦2•rD†Þs¥Ø¦µ6ÆvC$‡a,£]c·°¥^·NIa9|Ë¢bÍwHú›a.%û˜¥(½;…‡­í-³>½f2ÊÒÑ}}ŒHGæ7=Í„¯7‚ܡֵA¤›dº½N¶Ã;›;9ÔŽfP²'¥™Ojé&MÂXݶ0Y•aÀ9¨”Ô­Ño~6‘NûåÇ®vT£ÜQ=#ö$F”|Gêy ¬§åºnÝÏôÃוîAÊ›ùÔö©nCd߈Áê+¢LSÌ#O\D:TV9X¨ „"çŠF])VË`hº°¥6³bj:°º°Ó×/ºÖ6¾jŠä³Ð²&TÁO›øÇtÑ-ÊÜÛ”,"au®‡µ¡ü€¨'D üBZ¨Þæ +"†L[§áQ› ÄþÂ<÷ø¨¯^öA¤c³C ¦’§›êlªÔ’˜‰K†û@WC­Â/{çô¦Þ¤­ SfÆû¹¢ ”U×Sè RŸj$C.2B4R&Ȇ’“'ƒŠ¬üwÿ¸B„>2öÑ«”Ât3’rtfjÖ^EϾ™!Ò"˜{Û?Hg{=žÚaÀ4Æ\ÎåïVƒ©DL|wÑôþÐŒAÎTµ]9h}É I³R ë6¤(+@:¥ÉžÙîXS“è¬ÔßRëROD¸—ë‚2×qz4’<Ïô¬é¤æFÙ:" ÿÈ·@:¬ó¼…jx§µHfö¹ HÇ·%Ì&%ÚºYpš +Ë2lÍŒT¸“9ÓÚc\H§|š´ôµ­êãlð‰ñ¨ó’¨ýjéÍö.Š*ÚáFÇy[NN)3¿„!qÉßT<é$þì•ÜŒ‘ç#à­WvéôEl­"Ë­‡Çù¤P[@®[ϬüOÁ£; „®²òPŽ–é_3¶ÌqdZYÕŠˆ…{8ñqY)'ElY=@lžè..¯w\y¥ ·U“7K†3ï¶² +}“yÈ M«oë>¨^UŠ­îxòÔSÏ>騦U©æ •jç™[EŸ?šÕØ}nûƒ HGFn§A¢,ëv›…†h8•*Lƒúæ,×8ÌÆD $yu,·Å˜•¤e¥¡ÈZ¸âÓÆ^úéƒÌqv G§o`Àظ£3õcÇ- i× žsÛQè¨é¹e«FЖ1ptJZÛjI[.Òi×e£–c|{—ÅÁ˜š£{–’Ø4 žŠ²éÍt)màå£Á¬nÏgæÛm½ hTƒ[¢^I¥´º×Øm3}¶¯bD²rŠ×Xq3TiGΆB=®JF§è³Ì}ÌÉîÉcÃè°<)ȯ"IIÖþ·‡!©  X©%Û£å¶Þ'«ÕäñÅ EQIÌO»zV飉&Ú´2ý±ýŒ$¹.‹…°Žn‘;ª±å”Ðß\@:å²Xwª=݉V¨“ÁP_¿ù±ˆI dÿÊ0ù¿”;ClϺ tØxäCżÀ«¨ò2kw‚M­¹œRñfI¾‰mèvo¨Ú+14V˜ £„{ѦI*íeQæÇ2±´¤¶c.;fÅeø¼ÑíY¶áFQ@½§wê[ºµdXL:ÿl îA÷Ò*âg*½Ô¸lö(mzJ§ ÂòJêKh|ÀÖºJ»Òv«•\P:-hCôMø²Âpñ¤±Ë¥æ¶CTXXFæKÔð½h_Œ@õêyØ<$eAéPOïddRŠs¢:\Ÿ5]ˆûçmøN‹Ø¤ñ1œ›;ˆ‡û;¾ tGüöql+ˆÆ/?_ŠØ™ÁËIêáðMBsƒ~ åbjàç)YC%UEéïåM*´FÖ!ÖjB1Î0ÜI¤{¸Û×Þ ®Y˜WŠåÉï¶;R= ×¬mè!ß'E÷XB5Uš&lÙ¶ÓøÐ} –ä“#—o È9i=¹…™œZKUŠÊÝò]ÍÆ2£”芷E‰‚weî³x*¡NNÿrB}RÒýØêó10Ý!ŸL€$ ÷ÃýÒ×Óé>Z,W/$ïÃãÞIœãtÃ-6KsCe>­ 4*ˆ Ek‰J+š:èªâ( #qE·B-(ˆ¸§–oÉ'(Y\(y“®<5±”PñìN·#3 kÒ.÷‰ÅßÑf˜cÕÒ€Vccïø9Ñɦ`›‹þ½¬«PXËNÙ—¶[Ä’ÕχM¾÷-Á#wö‰µœ”ˆµ°)dbl͸wÄE@±Ê´h>¬PDãˆ-KRo»ƒ˜ƒ¦Æ¨;¦[ú÷ºVf6Œ}gí•©›è¾âÑÞh>^œàð;½"ÂÈH¨/-Ef=L*Dã³Cùë¨ögwáq¹|7½”2,UÆ9’÷g·î*òì8<=4çÜô;ëÍ4­mŒµ’ï‰rs•Hv7·|èÔ®dJðﬔ·¢l·’ÔKù_—ò"…(G KA*j¨ÏSNàlÖ®{ñïL¡ÎËó&û¼[¦\¡Üa·¹£g÷möW”i¦Fø7óÞô;2áL r‹4;Œ<Šðw´~èÞ®tðx]¬x7õ¢œy¬í‘ð]ç›·i†`‘‚SÞŽ{쩼¦Gb…ÆŽ,ªä¤H'+ÃúÇh!Ô6ÿNÛ\ë¡9iYUG<°† §[SÄ3ö¬\s´4­8èW×.ߪ¸¦Ž[i€gêm†XÛ +}¢W…t­=ljÐf'xÌ +1£m¤"+ŠÉ¸ÆØKw=1þ‚€'ÕKù¦5g¤ew,‹lÏ¡a§Ž‰&ÀR­2pù‰Ïz3N7²ëF|unMjX>ÉEBë0N¸½}(muï˜1h¶øûrÇ!ª7p˜¸ÔZF°>Ög…•©ZÃ~’Û9Þ«—'ŸÝ=÷š Ú:ÇEãB]cÖÚÍ[ àÉéÉ;½“Ë»6ó›w[òŽì¶±µÛÎíò¾¦~Œ¬¤$±g‹ÈU(ª mk‹jÞ H)¶ÃTÛm Ðg»\8Ã65ü®Ãèº1Y(ØHº„#µæ V­à?|a½]¬P"AÁ"ÿ“~ž¹„(ó²%¥¶ÔÝ:2° åõgå:æå#£´ˆéXßÿîù”î•w ~§·WXo8+)rê¸n.£ÚiaÇ;»í1B¯ÃTŒ¥ Èi»“ÂuY-éC%?÷‰?pØâ175¹—8 +0-3ç*š Is WwÚ>R‘ï€ßi§dü‘é¹+‚µøÞÖvi)Ñ-7¢¼ÖBI»$úÖɉJíË{Â]/ÅÖ™÷ê›qy—=unqOÑôe h0}Ô¸Œ}‡@{kå`è¯Ív}möî䋞S,x¥ #ÓÆn)"²Düv‰Ê…?czÌð0t±Ý;Þ†bïïð¾ö¡âù<½£(¾Œ%h‰ø»¤FtRž5*‰eËÑBͪaU»Êzêè~¹Ž“ …,„–+Á²Qi¿ç§Ì´—‰lRž¨ä–oîù˜Bà@ʢߡjn“JO:ú°§§ËœNº™öé{Ë)k„ùü…WÒ“|$<Þ“pµ´B©¿.VÔÇWÆ pDí¬¼oü•¢Þù8yBžf† -ëÛikø…¿£1/¥÷ðÜcH½fác–|´s üŽ3Çmÿˆ|ZÅò0¬†+êòP®·Výë¸é–UK¼È ¶•±ñw[UnOµ@¸|ä5"¡ŠsMóõA­Ír€ÚkçÂV-5šxFÜêû•êþ,Œ-á…£Èri?néÁ¥<›·U]Yº‘ì Ö°â&…¶«bgv¿Óq³4¨®‘¬'xiä¹ùw¨Q8¸øwú¼Ç^8f –™ä¥5JÓÆy)ò<ÿn«Ó)YÚ\±òˆî¶À™èºÅfZBcB¶Ë0;ˆŠ[¯¥ÓŠÊ'B‰ ©/È\UÔú`N‡á… ³û‚á…xÜ1ºDoAyÔO¯f…k¡~áð¨¸êÞÏ-†â‡àãåòï˜õ¯Œˆÿw"Þ5"ÞÏžäˆxR+¯c÷ÎD¼N+å/"žp•ˆ×å£ÏDå¸ç ‰·•ŒÄ[êBâ jX2Pú ‰§Ç "ñ´«HH¼õÏ‚ÄÛj ñôA‰§H¤HEâ1®$žµ3úBâÑù¨ ñ¤T$sÆ ‰G̳ ñ¤T$žó…ÄÓW$ž¢Ü‰§ÑöÄcˆ,HûEÄëìxïguZ‰xKÈD¼%¯3»e"^¿ç›ˆ×ŸQ‰xR2/þ‰x¡¯“ûËD¼®Ó‹ˆ×eÌ(D<»x™ˆ—”DÄÛjñz˜‰ƒˆÇ/yñP OJ%âIyñú3¾ˆx(…ˆ‡ò"âI­D<}ÙJÄëwØò3o Ôû8™ +o+™ˆ·Õ âÙ_ÈD<í¾ßD<…”+ i!â)¦ù&â)ö™‰xÄL o+™ˆ·U#â ñ£3OQŽ7Oj%âI©D¼¾º—e"žÔJÄC)D<Î|ñúÓ¿ˆxºˆ•ˆ·•LÄ[ê"âé(D¼~]@Äc.D<*o+›ˆ·´…²Rþ³ñ4¾‰xÏ·0aÉYˆxK)D¼­¯«›\!âõëú"žæíJÄÓÖ£ñ–Rˆx[ "žíJÄSˆöEÄS†¯ñ­ªD<…FÞD<Åà*Og¾‰xÚôU"žö§•ˆ§®ÄßD< +L ÏZEe"ÞV2o«NÄ3ûn"âÑÀúEÄ£¼´ñèz_ˆxïhvĹÿY"ÞXÅœ™ˆ7ÚñEÄã¸BÄ“ò&â 5(D<šo"ž.þ›ˆ‡:ûâ±ï/@<Ûªñ¸—ˆ'¥ñɽ€xz„*O1— +Äô,üâ`)@‹æŒÃc½\pxòÇžžož–·‡×(2OæëåžqxRÍ ‡‡ ¨àð8F/rÁá¡áuÞÚ éÿЉ9óðdD©<<ÛßÉ<¼~Œ7On’ÊÃ똽¯+¡õâá)_yx=2÷‹‡§ýÀ›‡×ÁšdqÑÂÃ#Äúâáu +2¯/ÚvððÈxñðˆnž”ÊÃCùæáI¬<<”Äóúæáé{ž.WááŠxñð:ÞŸÌÃ#â˜yx]ùØožÎ«<<ÝÊÃS°öÍÃSè¡òðx$2OùŒ7¯+›ZxxŠU^?Çððô„Už>«òðºÒÔ/ž¾Iåá*<<ýÍ75óð +¯c.<¼~ŽÊó«•yxð7O_´òðäÁcU<¼÷ù+çë®’Ö¯ƒŸ‰‡×…é+<<óæá¡^oáí žrÂ…‡×yŸzâá¡^çíúôß +¯Ã¬Ï<¼ìØ<¼ÞÜ+WxxX¨ O¦Kš7O¡œ7OjåáuZ@gŠå¸Oª5( žB‘‹‡‡‚‰4óðøq“óð4eUžf/žFÃÊÓ¶òðäÈûæá)oRyxŠ7W^g—÷ÅÃÓPTxxýi•‡Ç`õâáu:ge)ºÌÃS†ñÅÃ#„•yx][ž9j¸ûJ;½xx OQ¯ÊÃS óÍãH'óð­<<­ +Þ<g¼8œøMÓXhx Oÿ|Óðð1¤BÃåMÓZix€R + OÊ›†'µÒ𸆅†‡òMäa O‰½Jð|+ ûc¡áuúae¾ˆ ¯“ È4÷ Ï”LÃ+'.j¡áI©4<)oÞX·‚†7>틆§wôMÃÀZhx|‹BÜ¿ixzf•…†§ªÏ O£@¥áiØ©4<ùèÞ4<¶:…†×£$hÑðÆn—hxŒ<…†§7µÒð($yÑðP3 OB¡áIxÑð¨6)4Vžõ´ýFáÑC"£ðXp%˜/jAáY‡ƒŒÂ{ÀÿäÄò/Báh{¡ð:H¥ŒÂ³ò›ŒÂcò}¡ðÈÉJAáqæ …'µ ð¦eZ/±Ç‚Âë¬ã3 +O&7 +OMD* +r»‚£@î…ÂC-(<”‚ÂÃòBá)SPxÔŸ +¯_gEáé–TÞûfþé>0¤d_(¼NJ0£ð8® ð¤¼Qx¨…G$5£ð$¼QxŠÒTÞj‘Qxj±õFá±Ú+(< š…§íÇ…‡ZPxR* +OÊ…G]~Aá±é-(¼½Õ +°@Aá :…§'üÂcH/(õ‚¾îãoRÐëhãþ‚×aè:¼N™â/rr°óLäº/N€ëdu¶Ý× Í™gâÖ)fyœ [Gmcû¢ÖiA©7* u‚5-‹n¨&¥Ub ‚žÄS[ÍÏΫ»èUƒ–³Ÿˆ¶kÓêèË}÷ «{ ‘1µ™¿ªicJbÕ5•âsíƒU×´¾~Ú³Xu.ªWFÕ53u·ªC±.ŽªkXûSQuÍ\ÎçFÕIù™ÏÇFÕIùÙÒõŠªkÏFÕ5ò&|NGÕýL¯2üŒŠªkj/†‡ÃIuMk¤côMªk'ÕÉT‡¦!zêPx׃T'å窕T'õç–œ›T'¥ÏynR”ŸuýSIuíÄçpoR]£¯Ò¹Auïûø§¸Ï2Ìë - :©óóy6¨ŽãØ^¨NJ'Ä›IuRvû÷&ÕIùWÛ¤ºŸGPa‹£²ê¾„ªk˜gbÐ5Ùú¿VœwØÆBT_»ƒM¯“êN á稠:µ˜{îksêè9T: 'nÍ£bêðôŸ}Sê´Í¸®{CêNRHOeÔ©Îá£-¦#ê”wÌh£5Þ.y1èUªÏ“Ž{ºmóƒn+™A·ÔÅ kH ¶lò~%Ú\<¬¤×a‡,‹×íºõÏ‚ Ûj èô9v¡-'ÈüÏñGEÐ5!fVõâüü­{#è¬ùÐYt4j^‰ä;JÁƼžÝúö„r8Øî†¦Xãñ<›@'åùœ×&ÐqÌy]…@§¨ådz +ú.=²9.²œÚQ§˜tlTŸù°Ãïlè’’t[ ]'=«uEèô'¯Þz%ÐñEx•‚@'åPx+t´,bÅœt¦ök#è8‘®v ³_É×J:ML¶( +&_[‚n+A·Õ@Ðu6ÞW_ax5bxO:îÈ©M¸‹´Ðb Zh̳AGé{¶ Ópñy4ÇZ®)Ôȇg{³Î½ŒãD!êÑΊòRÊ0êBÐ5Ùo¼‚®U` #èšÂaZÙ,]£úÕÑ èš¡gEÐi±×¬fÌàr°ÇØ´9B*ŸÓߥ8ŠÏpó­:à Cƒ@'͆RÐ!0?ø‹…0Cpü‚º¡Ýdßœ>'”mÀç$4,.‰=§á홆¨Ã–"¼ïFžÓWµK²ÁsC=msçXfúÆÎ±ÕÎÔ9òd3Qç”Jkcn蜖˜zª +sîô…ÔBÎÙqoâœN#¢“sª˜Çܼ9ͨg?7nî¦#ÆSisf߬9ÀIЍjn ‰4·ÄÍÉåC@=8sí3mȘ9=ìÒf®©îøñ䘹&¿¾ÞÙ‚™kT\ccæ¤ …–f®Qçà.çÕV^êq\maæ$hÚ Êp}3e®Ñ OïPP暈G§÷·&xЙÿY)s¢aE3'…õýÂÌ5ZÝeÌ*¡ÔÀÌqæ¥ÒÇÌñá,U3fN?Á;0sz´¨^˜¹%dÌÜ3טÂîkäšb·D²2g®)M€{ÇòTn¸°m%Ãæ¶¸9m×®Ñ6E®É­P»6²Ñ/ŽãÞmÓæ’’hs[ Ú\3¿n[´9~O£à5ÑæPïÞ6mN +ÇE›“2¹b™6'•¡pÑæPîϹis(ZeÚœTVЋ6§/{k[¹†KæI\9û™>&ïãÔ0ŠDNÐæ¶’is[ Úœý…+±å´Ón¼5™6טÊG>N‘O ?_;.ɲôìPüÒ"¤Ž›#ðyÑhÇqs[ɸ¹­n®©â¤yDV†*Å4˜Z nNêÍ Üœ”ŸçtnÜ + ¤Œ›“jãGàæPî{nÜgÞÏSqsM#&íå7§«h;µÀÍm%ãæ–ºpsz)†&“Å‘k +ŽŠ›³)—†ì®>Äæç¦Í-aÃæBZ(ZeiP„œFÃkóJ¨99Òë8ùï¶IsŠÞþ\ÛVIsR~UÛ¤9”ÃÙs´wæÌö•4‡zžÏ&ÍI9µ[¤9)×4º Íé«ù™NškJÓ ŠËœ4·”BšÛjæšæ}¦» È=5* 9>-¥ªçÇ«PÕŸFA`W™2§¨ŠeZ2wEÚ'sêèÃò.!æèoù›1w]¶Ò]è8kS?+aNmÞíuQmá? W/·„Œ—Û¢Óå›×fËißöœgAË)ïÌ d9yh>ŸkƒåÎÓH™+'‘‹X9}CQPå0ƒ;¨mAåÎ)‹ûØL9±›Wq’ÛÂ&ÊmÍ€r¤{6%N~öôOÖ]žCaž8r2Fñ¬dŒ}¼æ¬9õ°­oˆœÆ¡N©˜3äB(¹%AN¡{Þœ¨ËÐXñÌ窕š‹›Vˆû¸é΄[JÈm5r†'£näbµ “rÊ»Y\-r +666?NQŸef¯ü8EÐll~œN|Xíe~œâ+£»MŸî†êÿû³cK¼8µñ +¬‚u™¶øŠã评Ä r[ɹ­:AŽB¥û¶,ýÎÕóYߪä¨Ê<éð^](#ÚfA@õ?KkV9+A®Í3A®Y7º{ä¤]+¹¦÷EIœä´·=m©î9]~7¿$‚*“} ä¤XÂ$ršéë®9n'#f ä¤ÌÇñ s€Œ}V„œž"|×Ak”ÒlÍ r +ÕÚò7#äÚûðÏSãí>XB®«qÁó\!§(ò°—„œâ5&BN¡ bF!×­r )·v;¤…^©2AË.Pr¨J›,†¡“Û? ˜™Ï…!G¦BãìbÈ™sîj‹!×5éj[^rP-4½B®Óп!Ga´Âž!`@cÀbÈ©ÊúRœ<rÄï9+CNu×$CŽ_Dƒ GÈé2³äÈ9‰ƒŠ0ÈI Ò½r´‡¿>³ä²i÷½r(ý¹7@EW­ä¤>\êÈQû}×Èþæc£XÈ)neä?çǸøÕÎ7õgW~œŠ2yÃ?\‰àÇéºB-Ìø8…ÁØ+,|\§¹j§A’t^ÁÇ5^sl|œbeM鼂“Š eáãô=ŠÇ.|œ'•oáãP´ÉXø8¹” ?Žô†þÀÇéK`ª[ü¸dL/`æÇ55´ä™ +~\ÃÝÏÍÓHß‹Œ³qrnzC© N{Â1~ÿ:zœå>g¥Çi ».…FkO¤vƒ×?‘Lø8‰ž +ÚÐG6G[P¨ƒ2"[³ÒŽ\¿-zœfíÖ¬GKïùEc8½¦9äÉÛ)ý†ûqÑã4ž×mßjÑãšAaÎß=Ž)‰ð}Ðã4ÌcS*ô8]³EkÔF»ŸŸ†—(ýc¸•"•ú3´Z^Š–$(ÿMðqœyOSV—­aŽyX ø8}[àì}/ÿô Ÿ9>ù'zœº×^´Éöþ‚˜—èíì8y—îë®è8‰,Vƒ'_i€ã°E]OåÆiuLä0°qšÏ#6¦×]æúgVh)¬OßÌ85ÇÒ‚j!ãN ?³ã´D˜Ï³qZE<yÿ§#>_´8iZ,XÜ $䨰8•Š¶ç®¬8Ù}¯ymTÛ4X¤Þ¯ñ>}̤¸§Ûö`âØzjÖpNÜÏrQ¿¨WNœ¢íö-ƒ×"¿¾8qZöOØk™§íñ`. N‘MíÖ'ŽéÑïʉSà9Ý'®Á îçæÄ)1)öΠ8âÏ36(N +ÁµŠCQP±âšÕ…Þ›‡òô¤8û¤O¯¤8}³ŸµÓ±QqºbdãG,Á>:¡âË™ƒç@Å.<1´*®©\Ôö–§ó°)N÷ÃÌ}AŠ{ßgPœÚŽþlNœíէϳÝ~¢ÄaºÖ&) qš¨°g#%#â4åŽsnBœºõ‡]Ÿ°vùº}'>ý˜Ÿ¾ñp-*N5'Ø)3£áôo2A†‹}XBÃiÇÄEs2—Ç©s€´Þ˜îÊ_åyw$d Gÿ’ ;ÜŒEuäû•Óð||†ÉL8@ ÚÜN&@ï A¸Ìðõ­h£Ä© +œbÛÖCÕipª|»¼ÝèÕ)ùã5lñá6% +NâüœÔà TûmÛM@p°¯(â2yÍfÆ©Õ1T¾då$Vi’jþÙ#wª)š“ÜNÆ#¾¡àh{|Y¯npžîBDBO-bn«*㙑ÿêhÖœ$&•\§}ðê<(xäÁetö›záñ×ýF«p +ãúMœ¥\ý&?ê¸(´sô›¼p?ûŽã·Ì~SÃÖVÁ~Sð÷Æaì·Æîl~Áß4¸°½ø[£ä7œÓß0ifú›"D½ýÌÙq^‹þ¦s×aåkËr{57 ýM嫟Ó)4|l÷Yào§/ÑûMIn$Ðo2uÒe,“ßTŸBi‚ƒßž¹d÷Mñ#F¿Œ}»/÷õíÖÓø±rbÂÊ@ÐC3-æ›@=J%.QQUsý8ñ²ÃÃA{1Ó%§ÙZ–•ÓœïíþøÃ“qoÆ·Å{h+ô¤:ëM=´´û/¨·Û›‹ôé¼µ zƒ?¤ÕXæ¼éÑþô¾1oòòÞpß¼¹™:;zç`¼ée|>Hÿ_C6˜ Šõ9Nq ©S¸˜Q‚ï¦-Äâ»)·Û?×Qoäÿooo›ŸO8‚ð¦údË2àíê¶g]|7ê›ï6}Ûœñnó +c–ÓÝ4 +ãn ¸Ûáß²ÀÝ$âI¶›„³õv33ʨd·ƒ6®sƒÝŽaÑÇÅuSKÙ8+v6jW{7¨nC £)@ay´²0ÝÔãðþε'UÓ+›õî +–w.@·áŽÅs“»cžvÑ9¥G¿*ÍMâõœæ¦D¦¢ò‹å¦Fåí¹+ʈýAnêRÞ)åvŽB¯7DÉt@Ü”çúŒ¹nJ¹—!- ։w©„থÉa?ßnf—Êø6=r÷mý ÓA½‰õQg¼œÃb•…ÝF]ÙµÉm¢ˆjn_à¶AãåY¹mPÌ!8¶Í:¨ÎMmSŒ'?CÛÈÛó"9µ­)ˆ„A"¨mFâ¼2‰Ú¦¹„!iQÛH M:Þ9µÍVÀó Ûðè›Ú¦å³åª3µM'[š5¨mz½m©Ô¶Ö|R-Ô¶ªêu6åÜж.¬mCeÄ hŠnÙ‚¶I±Œc†¶I= µáж†Sú¹7´MŠUSeh›&Ñ9ǽ¡m$ô-så5“cé-Ð6T= Ú&ÃQ@Û$ü\§£@Û$V çÐ6ÒÄ31Ûš-Ge¶5Ê·®k3Û¤xlÉ“HZ›Ü„‘Älk.Hº8³M‰{¦œÙ&kØ Ê!1Û¨ï:ïc3Û”{·\{0ÛŸ(ËÌ6¥ff˜x÷v^ ˜m ø}Wf[£×õè›Ù†Bî  mœI­l¦¶I%,³°mRX5¶Mÿ<)ÂËØ6ÙW/¾¶Ø ×À¶5jrµÎØ6©˜¶­Ñ&Ë )„D¤´ùEm“ÈdÐ6."!€¶¡ÈJš¡m4§^@‡¶)™vwÊÚÖÎΖ¡m¯óÚÐ6=%æ=hîruÚÖ¾÷¹¡m:Ó¼mk”IÑR3AÛÚ<,² m*ò#:² m»§}m†¶5°óÞÐ6i“@Ûš|F¢IÔ¶†MW?¨múåkïHç›—MëÏDm“HYÉ¢¶™27´­œ· m¨,\Ú&åPhbAÛš±Úî +mkÖ#ªoh[¾.YÐ6½¤öYÚ†eÓÆo‡¶ñ-ê¹ÚÖ¸Pº†ÚFÉ#ùM‡¶aÖ'ÔÐ6Õ?~†·V +h›†\µ Ú¦qÇ¢qm“+ÍÆü mc‡Bw@ÛZ”Ñ,h[³fe•ÙÆÈsÛ–hX WV鱉mÔ]`ÞÉÄ6T +ôÙ&¥Ÿc3Û¤ Ɖ m£@ãñ3mÒ"áüœÚÖ aqVj›lù3RPÛä‘ÿ(T½¨md¹¹™ÚfáòûÞÔ6jЬµ•SÛ”8#cX¨mt—$GÔ6ëOÜ®EmƒèΘ’©mÊêQ·¨mн³ûYÔ6ãF¥¶CXxPÛˆå³O j[§­ek•Ú†Õœ·0¨mTî0“µÍøóÏU©mÝîöµ©m(6Ú8µ3­“C¢¶©w¥…š‚Ú†­Ÿg6¨mXºyK2µ­ÝgŒpQ‚@e +½GœÚ¦ÌŠYK2µ3ù›AmkDîp¨µM°fŸQµM_ÄÖ*Amë¬Ümä–yj3¶MÙ¸Ž++°mªõ°@`ÛTqz·éUè†qýY¨…cŸÛG› ¶©*Áîx¦¶uH0ž#à«kmþ>£¶Q¾E5t¦¶Y1XßжNgÙϹ¡mRüƒ´Mª™0 ÚFY“E>Ú†r;nQÛH`SáØ6Ëvéê¶Ê&„mÓۦ7ÂLÎmSnÔÖÜf@jL1nÓG±è n›¾‚ ™Ûfj¥¶)ÓNÝÔâ¶éI·-EpÛ(êëž¹mJÛ‚)Àmô¶¾%NnëÃcXݦä±5Nv÷–öÁnÓ#LRa·é Ì±Û´à³µI°Û4†Û|_| W¿±Ûd %Ó½Ømšî ?•Ðmò]ŸÃjÁ@·50ñͲu ݦ•¶‚…nSFö° +sg·5š +i™ÙmZ[±e°Û´é²Àg°Û”Ç£:&£Û4:°ñŒäôåCÔ·Á¼*¶íl¶ê\Ô6…!”ï fÛ+Èü+#ØÿzÈ6üÝQl Ù†€‡=Tܼ„ŽlC¸üÄ=‘SR§Ý™mz6ÍdÌ6Õ$zh %&¥"8ÁlCQ Àb¶Ù1—W,4± +ê’Ù&Åb³Ál“‚Û¸0ÛTÌÆþ@+éÇ«²Mc²Y‘2²M“ƒ-8Ù¦‘ƒè*ƒ–k 7^A¶i‘@·”…l“ó„‹¿mŽ(8/#se0Ûð™œÎõ"»&»_a¶¡bq fÊ8çf¶ñYó>*´M-÷¯‹>w` œÅÖ©Âõw{1Ûè:V˜m=Ef¶m%CÂ’êÌ6šÝgf\of[gýüi鍿a½`¶ÑÛšæ ‰Ù†H‰`¶¡ާ%f+…%Ca¶I5÷B0Ûºb<¨³MЦ¦‚lS+nJFƒØ&Ž»‚ ¶%!Û¶Ä6µˆ§1dÛÔÏþ l£§}¶©}¶%%ß‹¥°Íºö'`›îÅ Ø= ÛÔÛÿ lC-À6” l“ð¶!`ð‰l“ò¶éQªÀ6ÝDr¸‹ÄŸÂL)OmG¼c§• ã ¶Q±È)ÛP§±ÑîSŠE/ƒØöÿÉyå_Dl#Êfg"¶)ÖIkElkô²™‘=ɤyVb™4«öubÊç›ØÆ™Šqb›T‚˜Al#zy9«¥;TñD¨?Û<ÞÞTÕb;ŸÛúò,b›ìÖ.'ÛÔuƒMÝ"¶Q¹†»)ˆmͳÛP{¿7± åp²›Åœ>žUÎÀ6ågÈ;¯Zg¶)p=Ép±Ma_ë<Ķ÷Xù+çí.Í lÓ>˜ÁÔqm‡· [´¶Ã»`X›’T$«eÕÕ7ªíðÚBj“òVc:ëô¡Ü°4Þå±pÚHù·kaÚpsSÚ0¬a®L¶ùx„;mêÏî:m%yÏ¡Mé—vßÐ&árîѬ4mT<›D,Ag; Gm6›þ€ÀÌfSß öµÁf;>fLZh¶%d2â57˜M•åÖ=æÚAÐec¸»ÖŠ]“(›fDj¿3”ÍÚÆÜ2p?¶³ ÒÚÝÏ:d¦÷ÞÞ”6õªb%ÕklÁÛµ kj}k}Œ°¦#l’I|µÓ;S/¾ÚyXG¿…WûÙq‹ +]íðþ,KÔV¡9ØjKÈhµ-BV;¼“׫)JÑVæªé ˜¯Þ¹jǽ{Ì‚U“À²9SÕïgCÕ$0S_Ö®ŠT£-…÷NT›Ózæ- Ú2Om‹ŽS#  ËÕ·j¿.éâ 8Ǧ©ÑôWÕS»>>+05a ¬6Ðaj ÊÛØŒ4ÕcñÁ¥Æþî|úVeqÛ‰£Ô¶’_ï­J­õ{;7@×X!½æÃÌR³îB”„8KMýIq;I­Ù‘’IjÖÏÈÛ+€H‹¼q©iÍhoË:ŒÎ^ü'©©jè9Û¬$5SG¨óò㎱Ij¦\¡Üa€ñV]‹¤†Ã*Xj(ø22Kôôs-”šþMVc¡Ô´zþô +R“·ÅRùRÓ6Ëü©ÑÍzï$šTïná 5)'ÂRkÖé($5r±ƒ¤VêÐ9ñˆÒÜ ©)poÝ%œ¤¦ +m¸ÌRSTܼ"¤¦mŠÝ³©I±][€Ô’’@j¦^÷©éšZ*!@j4±Fw ¤†ïgÜ›£ÖN¯Ã]55ˆæ%.5©^Ðæ5IO¤Ù^@#ûpÔZ4­•èõqÎQ“rY_Aç¨qŒ¹#G¾+dƃ£¦DµGMÞ›2G­ø:Ûæ¨I™¸‚£Ö¬LtTŽªw£Æ‰ÍÉsø]ùðhM¹—TšŸØàFMåx惌 +™ŒQÛÇF­1‹µ ¤Ñœ禨5EÕéÉéÇÈÓy÷häŒwúIµ­EM3‚( Fßíè FM»‚ë¸cx?8jII µ­IM§‹0t°ÔZä 2K Ñ09M­M¯¨šš6ÁZ‚d˜š4ƒ¦†ÒÚ†©!ÊÍ05}º½ÅSÓ=Ђ’¦Ý¹í€3MmÒë°óã>³€©m%ÃÔ¶05ûsÓÔ´Ofajr'Y0/T‹£>Ï‚©)m;¾ Skô¢ù´ SkÖóÚûœ­d˜š©îk¦†;”B’€©5dVpš`jR½w„ÃÔ¤X3g‡©!Ë05©>v8M …ÍASk@%˶hjº•§EFSÓUö%»´„ÄR[Z ÔHµ€Ð‘Ö)¬QjL¿´z]Ç)ûxÒàÑPj[È(µ¤FìZ*œàŽHÓ8xR“Qj Å2@™¥¦¯ægŠ¥F99Ag©m!³ÔL¹=,†ë·…H#¦f•Ð ¥Ö.7ϯÃ)}>V'bCÐý˜¯® Ôè+Kgë@©iÑAÕÿB©)æÈН Ôtœ.¥Fh’v¤ÁHÃõAW»v¸Úúʯ㚻HK-)‰¥¶Õ`©áº™óÜ,5þæó…R#Ý®}üB©uz¼?ÏF©¡DÊ(5TË;KÏòî.gD°­Î=£Ô¶†—RèDö)PjII(µ­J­ïÌ’#Òz®Š-Ên¼—ª(<>ƒ…RS/*L(5T<¥¦Ï³æåSc¥‰cÀYjKÈ(µ%I­Á·h©9«Þ;zxýÖÙnÿÖà R3åIƒç,5@jtd4@N#9ãõR ¤Ö>n®] 5kXm…~dó´ôÆÇ–1jê¶C=EPÔT¨ "3ÔÔˆ"P Ôn7"MM2)bÈü4†ÑÄTãB}ŽMO[B¦§-1èi#:ä‘Ö1 $gÇRÀ¸ .ý”Iᕱ;GûH—Gš‘Ú¿ÉI™Š:ͼZ'WX­¿¿¤Œ¯~¹ö‡HÕžƒLÛläÙ§x¿ó¢í ÄIó:‘±ó*y5#g tÏ[¹52û(àÕqˆóyöÑ~#`ÖúûÈ­‘/þrd{äB²),­úP®Ö^è¥2ÞÍÚ¢— Þ{©ÚÄjsË:f¯8¤Ù''äIã°ûþ{¨ÓO.[^ñ¿½;B + ’<Òš•Q;Ѱ×?6¡®Ñ× ÃÉÓ6ô޾EP¹¦Ã- (Q dV`HzƹÀ:HîàQPbïôY:¿…ÈšM$Ò`¿Ðè·¯d-á-«Gl‰ô€Ä©%OJæ>ÈQj°¿¥T± DFÎø1FU„(5y:j³´(…ÌÔÒ±^`UôcžÝÂ¥ZÈ×n! É'5ïd'’3¢‚2®ì“}lna³t ÙôMWò.’éù±À „ôõ±,΀‚K$ÒÕt¦k6d®/"bHÊ” Yoë³B¤~Èq1AzP$ìVÉELÒ-2$Ò™+C`ÉJD¡Ö¬“à}O./¼dR§€J>i\#!3†”g‹Ù˲˜É,K'DÆÔ+1J4DŸ„+·q­Tߨ¨…Ýò‚}Õé2X¤EGE,‡<)uËd¨ñ“Lk_ˆL5’àÏB¤Ã…]eùk€…l9Ú*âœ~Œ¸s™,©B˜dõ‚K›î! ™éú±Þ†é`BôYZ-â¼¾P.à• \ÛÖÛ,wé d/+«õõÈFE›ÏT‚±.<·Q^"Áz©ÓO2ál ⺤ û6 ¹(‘Eg+1Z +Ÿ‹RÖ• ðræÕFyÁØ©,D™‚¬“ìº<¨0,L‰ÉÛ|Šà-Ä“µwN–N/ +3>%Óq™KÖ} ÛÎE}¶ômCÈØ ²\Ȭ~ÄPŒ ± +Aej‚åSÄí§÷¡oËÌøì +×ÛlOd\‚²q.ôxö<’ÍgàxÊ×z‘‡ˆ± ‡®<«ó…"DÎä Þz'r°+* é“k ¨tµ z•š0DL&Êéì¼.óu·ò¶yÔ« prÇ-¿¤ Dº‡}ðz– t¦ t½7V•=¼œÌM5 ÿ"rU©×ôãmÔæ¸¦5»ãO¾y’ÚLÉuª6J—õ'Ñ7RðÖjÑΫ'£7tÙ:“¼ÊÀK?'ä,9Yc?7PôÕÕæU›J¯æ4ÿÔ„–×>ºhÛÔòÔ”çéG'äµÖ»‰¾‘<ýè²íuÅü‰²ä/··ç7—oŽóšÁö}Š$ñ¬Ls þiìÕCY ,¥­f4½q5}wMÞýá +;K«Ä>oˆÖŽAC2ðBô¸u'0ñ aõ! ÷k€‹Tȧ<«²¬ €£Õ€›q—Ÿ?ÇT*ò­þAí‰#û”åù¡N/x²<ÍbT«Íëó@%ôÑþÐñì­d¸Ó;'dÞh/Äzz!òú3ù`:m™qÈ3íGV,ýH.¶î¥’éu àJ?×5ò{û\á•Yh‚6ö÷LÂ+Êuös—½>‰ ä¾× y&µ%ÁN"ó³¥é…JN2> G‚³gy£"‰“J´X?]¨Ža¡¯:Vb6âlãÐ־ѕ넒ǃln Êò=[§G á«(½ô~œH®É)D[9Vl'k¤ ÏŠX$í²2ƒö×»0h7X(¿§ÛøJÐM=Ú&Èó‚D6àÛ±>›Ž¢1Ь_c‡Kû\è¤-if6m]1.,ÞéçÆÓ'ëZê“Y¨ï´2Hy¹Ò z6öà¬É7Ø&gÉE“?#f0µ:ÄLN”ØÛÓP“,W(ƒ<íœ=²|PùÓñƯY7òdC²Rà’Y›]øQz!r"=\‰FÌNÙªs.é %zK†p@ÁYù»„`MÐr• ?ÅÆŽ=ž}ÐzYC’kZ¼mSÔDÜ„—•­‰j‰ø÷ ¤í²dsß )5&´×^`©Æö„´ŠœîÄ»¶©“:šS,b¼v£dâ«IîbN«¬K :kÃGm{Üê$ûÁö‹C†s” DÄÐG%²´à¨‰œiEvœ‚z öZEž]î•Hp’IÄŽ·Dê³¾· ßV[uÙ™ ÌÖ­ÙlY†ÉÈ57JÐ5”sË ½ðaPbD©–ïéÚ ·¯“\Š £ž.ÆÈ[ÛØƒ³¶¦ë¿†Ò–´àˆ‰ –&3iÊZqòlIíÙÁT[bÇ7öà¢ÍXï:û$o›ÁºÆ<²­›H./å¡—BÌÙ¶ŸÞ²'䤯fh ë$ÔIbt­Vi%±”[L| b3õölJE½G9D#UÃgÇ!¤!X ûT¢G>‡Úm' ‘..ûÜÒi}VFEU{RmSáöoÖø‘wÅmZZ[r–¦·)Çn”½S™AC}eO©K¢S`}qˆòX1â ž@^Å:ŒK©\Ž­æ¼-e²#Ì…¾—2ºC Á¶u¦ÝZĪI¸R³ÏèïWS[Ÿ/¸±HñÞÔ—¦p M•“„QßOH9!9˜£ ¡ ¯V\—¢‰Èèš®uÖâšÚ0Œ¶ïLkÞ/¸.‡66?éA_š¿e0Åv¥Äù÷i(1›BÞNqÆlÒ"9ëÕû„|ël×{›35y}´yÚ“CszzÙ‡›µ?%»®Ë­‰f) XÆ’ýØnöMö6‹95é<¨‚ƒ+M?âØ@;oúBð­5«ÄFÛ¾”{?™k¶éBÃd“xœaKötãÌÈ,"õdz6÷¶ÜðX”ËØÿÑ‘×úÿ¾ Ÿ ×ˆ)lX–åʾ_xø6jIBìŠI²÷Æm;ñã¨f …4vªÃAZÌòp€ +Ñç‘(›!JÌòpznàvÊÑØêM<ǾÙv³Œ] :™ˆ\ÆÑ)ô”aF µl¶z•©,E„é<¡qf.£(uªìY“û ó=cë\Òa4ÎC–µÚõ©­·‘çJ›œÐ†!MÌ=Õ_ƒT/âh_ú8˜¹7:"ëæ‹­Ý¬!B ÅúÀ$éCjNÄÙÜNu1;ØÃ›*–ûÁœ™2EïÒ“â<}še´Ü¥ ñDQkö·àq6tbbåôf2©mnå8ÎØQ>J(Øb«ÍmèÉæt¿ë~´ÈÁ‚  +ÐJÉuÖô4fnÇjs#Ú: á‰/R?üFÉY[ÇME½våÁSR2s蔨À¨dª–íê\¥ÔܹEÔõ#«1KûJɦE 0ž¨= zëœÜ–íêéÓkžÔé1k-VI(i£‘â;‘ç ææÇõTgú~ßûv*Úâ²Ùv.vƒ¶r³¨ ÿlì–ö7"붨È(Ñézƒ¬Ž†(¾V!Êu'T!½ SÎû¢ÂTõ@ŒöhTÝ §\”†QÆöc±xíWй}K×è¶3âlãÐ,(Zy&³!SEC#YÒSVJîTGAöa´Ëe›Ä¯ªü^¶«D¾p1N‰-$XŽºÁŠèè+%‡ìYpf%æAˆYý§Ëvõƒ¾“ uX÷wàÁ`Ñònyö^Š&N1qQÉ6·ˆPgf šŽ¬Ç€ï&Ó"—=7žÅŽü$–ƒú•Í|Žª§#…Rídüj6bë/í°3k·yU³* ÓíT½\vÀ&ÍMÂŒ¬ˆx£ä›ñZ»v¬Ä`žÀ®Í]ÓXÌñ®yð}¸a§9' üÞIT¿DDKvZU‘Ĉ³èÐpÙ–T 2SûÆÈ±orTbe –.)±ïQ5×"ÅÔϬ•T¥ù @Ìö¬©~Ëh×P/4š vÉR}±ènqçA©¬vbÕ:(±TWˆ]RsäfY˜µŽšß9kHmÑõE;–n°#¬Í +®$ 1H©Ï*% ƒ,ß>Ûܨ¯À¬šÝÇ›nŒ¬î9ÖOÃ1 +˜[uÒ€¨7Ô‡æÊ@ÍLCœ¨Ùç(8Õn¬¦E>ÞØ"ÈY…3'øÆÈÅ… Ùˆ¦¬6®ãÐJ<³Bk@ýO$ölQ³èÁY[¢Q—w®ùÒÄÖe:iÞ5Ñg.Ô¢ÿ ·EòÍ±Õ ›¡Íf£mÎ>?öË5¬ÈÐ",x^~ÎÆ:]WLQ`Q|;›VÀt[Ì!šÔè‹6'ŠA$à±ìÁص԰1¬|c]‹£< +Á¦'Ãy ) ß?g0x}VC©a.ЪrïûwFiÏú` Ć_©’ܺ5‚r* ü1NÒ‡%R °/²„ˆE”Ú€™\ÝÑP€Ý«KFm1%ª+- wnì€)IËF4ßB#$wÉÈÂi *·g)|¢Ä4Xæ\æ£Åu|TÑZhoDExàŸaXï—Š#¨:êçCÑæAÕã @‹Ú£ÌFƒ*x¾ÿƒC/Ìš¤„äjóçÐ{ǃ}¨ºToÇ t»%›ñYPdLõA†@t*Ú|jNO)óÁÛ5aA Šg›?"®µJЇ YÌY»b'ggp©„úvŠ>õ•’Kg‡Ÿ/jš°Ò”>’øˆQÁ¡ëÔ|`éqk×+^!®`ÏF ïå±c¹ù‚²Üâ{Öì«”m¡{S¯Ì+å6&{rf1©ÖÔø=÷fOSf凅Èd YM2 Ü±m{ØKjáé•/Öî{ì°Î÷á¥Ã±aQ.Yç1ÊF"ƒŽòµØ\“)« hÌ$ ÄBèíÉX†Ô0›/KÌc¥dfjéðÖ‡èm}x"ÛÇ’¶Ëë¡­Ý ‘å^PØJThC”&ˆ¨èÝ)3ûh° ÞÁdœÇàÂJÉèE÷¢OÆædc‘Íæu?„Þ‚~( ¢î‘Ú@“ó¢#ðƒY£Î2ô¹õË9ïŒt ^Ž?!¢ ‰ͪ™^Ö Lã]9¨¸4‘%)…h¡'8Â8š:¡YN23n2†¨ˆuŠøâ„˜rÒÞöÍÍ•\Â' Vz#Rz£*‰ò;oåw»ãÓâònTth‘2mòdºh_1õ6uÍ‘RäêÔÜÊ„rÊȦJà—Q:§¬ü‚šCÎé+j€ÄA€†ºXjÕM•@¥Ï.·XJS™Nw(Èê¥×Æ”¨H¬ÜT=£™ÐcÜ ——{6+2Ïzã kÆ –%6k ¸"Û9áJ0®aÔ{À”aäPŒY*,I« 7‰âW:‰¬g"$ÃÑ¢SÅhцxCE1ÉE&"Ë™È"D\‘׃©¶Ñ‡lð^7DR`ø¨M€*5OÑ&¿‡KSÓ¸„à±,Èg²¾ ÕJ¢Ô÷²÷ƒrWKªVJög€“ÓYUI´@£F?ÞïÐ jÕç›ìQEoÅgA£ÅüÊA³ýHî‚Å/Stö¬YiQS\¥Uµ8p½jÉ­Ø"•ntEöBAÏæàÙìÒ²óͺÔfÖëʰ’›@§Òh ô®)¨ƒ·Ùb=A!úÁFÕ²ÁÕDaAVG3l +­Rµµ±F?_†u9çdÛ«9å’ÊMÞ-b Dõ$I¥kk¨Š¾îúƃ©—D 9Ltç2$u=Gß"Ù(/-îy¤Þ©Í”$ED×°(µµ¥®ùÈ`Áé“ÁÙ’'=(xUŽé'žíu5§ûFvóþQbV‘˜¥"Ý…ÀB/Äùê£vReñ 1f›æO·Dk–!Ò•‘‹¹‹BÃ0†dýJêÊC¢£3bßY<ÓÕFÍ ÄNÊj +å/xoO ½‚¬þ,çŽ÷&Óœñ^µðÑŠ9ì I‹2> +¯Uƒ[ˆõK“Ã6 é7tr0ãZÈΈ}rÖjŽ6.bÖ¬ ™7©M"rc“mò!Ëâ a» Áä¯)X¸ÈE;‚pY¥X.}J°aÄ$ç…8¦RÐÑPQ¸£Ù`yYg!ùlÏ–d†aT“U6‹m2q7œÐ¤Š%›7(Û®r±Ú‹P¡€3;ËûFÜl[š?)›ãˆ6[2þRõv°‰a¦‹½?òbT™RÃФæ¼Ç“Þ–ÆŽQzLRùANL¹sbŸ Í«½‚Ï•aU7Ó jÖ§w8¶’‰´Ñäb Ôže©~}6˜Î‹rQ¤nÅÖ@|V¶èâxª ¥¦ßàÙÜ$‡×Þ†–Z"+`Ízu:esi+4Ç'“X0ðnwf«çØ&Æ·ÈP=ßF¬`¡jb  ÎŽæÞæ Bf0b6­‰hø¤žù’NOß ä~ò; f›»¯Ñú$µ›…èBT¥#+xuÔ«„‹Å¡8´Ó& 0­ŠO_7¹ú?©¯ôÙ1ªÞ©B†ë-B“~йÝD(³6›õÖ·J ¡c6åwÈ*æºãÎͶÞZ_iH;´Úìühbõg£ÙÞÅÖ@HNÉ£΂©e¦Ã{  ædI¨bî{?g0Ô•hœ?ª¸_\7O‘*©B´øN’ËÁAÌRÌAX!šúæsÃK ¶»ÏÍËYÆé.E*ª[©˜`7l#Zõæ¸ï‹„VpÇb4„o 7|¬7¡eéùÔ cPNiÔ¦åPhpE”‘-¶båf†mhs_ Ñ6!²doÆ w™~L]ð†êâ&¹áIZ-eìó¦v!¶g‹éNѸÇm¼qmQê9©¶lqÜ4©*HUµž’L{E‰5[<8•Ø5½Z9ÇŨ ˜ŸÄÇæeH äƒáätßxQR*,âäÄ2z@ìÌ”³,ÒMá½Ô²*©¬ÃêJ TºfEp‡[ rÜÌ^YPK”É’Nkyr›yÉà¥)ßGB̹·×¶Fט Úû–&ZfBŸ +LÃ[£Îä}¼Ö@RTLj ?j®©¥òº`˜Dg“ÄÐ\"QüêÚYM€;Œµ˜QBßQ›‚t¹5§qp×´3ÁwðB»d`ÎÁœBŽ•Ÿ µd±¾¡eòÖ½ ÄnÄ,9DŽÞm{6k¼¢Î mQ2r¡Mé—`5´´ð~°G›%m˜+-#[dð­lf¸}«&s:ÍuC¯r±ó·Æ”–XJ<öʦz<®4aÊ\l.mÜó¬>×(ŽX›Z×Ùç,ëÕ0¤ $ë¸ÔIò/-:³ÁVLóE(¬ë¬*¢Þ²-;z9Ðng +¯%])Ù´½¹Yˆ] åN‚qf·[»‚EBºØ²$‰,Vš…n˜Þn3ŽE `ÞQòÆ}›úO't‹;;_ìIs)8ÞM  -ðnÇa›Äõ(ên +(sk†k Lq£Ëo¥ä˜-‰ePM¹»†Jõ°•Oˆ5³`Ìm“³¸<¨d’²Ç ãêqÐPËHXæCñ-ðÙmÒ‹ðåp-a¦´œzÌm´Pi?8 ¿OÑ5ÅÒÅ–ÈÀêcL¿8Kµïs[œ’ΛN¾7ŽÜ7t˜ëŒq|s‘‚--ùø#×9C'ûÆù]n©£zlŠ‘Û³Í­|Ù· ËæÂØÀ˜eú ß—–­. [Þ½ª£B¶bžÌAKR‚‡Vç«/†QÜE¼3ÖG1µeL“üì–aÁ*ÛV*£kQì~Ì¶Ž£°umHË"ÂåºÅ’L×°ý`¹yÄ?[–þÄÿ½2r4QV£ ’Ý[&Ÿ¡÷ñdË~éš>ër ‚–c–zî$SEˆq,µa"°4¾çUÜãé MP,•C Õ+Û«H!¾µíxåùhî[M³¿¹è+=Ís;÷œ.Nso;ÒÖìý¸­Ô2¡½wölßÙ~à=Ǫy…–~L´zdŒt6 í0C}Ze''±nÑéBg•,χ†Ítrw„iŠyîÄq|"*|ËýÎÁ™nš’Ú”íÒˆë0Ë1ËÍDBöÍæ1ç8ï~ÊJºd+QühÇôÅr¼™|`–¥]õú~i1:)5û ëëEÙ4«Í¬Tßbç0Û:*.´Ð7‰P¸c¤3\ÉÄn5° nÙrf¨—–É{oÌÒkàTV'ƒíºv4ÅV!ähø¿è$=Ä`P6*P'kž?ÁÓóYË6%š³+( Ä–_šVX—¾e´zÛkÆ®À h`}6·ädó/¹fÌúft‚ZšjË"¶ˆ¼ÀLˆ©mó¨!&oµÔ»–[þ~˜s?ÏhŒ#Œ‰g^‚±JlÈWf“˜3ÌÜK`yA*?E3 Ø)› 6Ç6ŸmáE_A†V, XËÆ©g¯o¯Goyé–^×:ƒçñ¶ÒºýÌñ“¼0:µ àÊ‚¢'âl§˜åÅób!ËQHÙâóŒÏYÍKêeއé^’cÆ`2Ã0ñ³†bÉ ,8*¾Û®oE¢yIÍw ±Ö¼×Ï3â`ÞëØ´Õl tÝÛ|ï ÚÔ§lu¯²èöA¯¦6âèl7-+´ŒíÀºwÅLÝ~¹¡¨Â¤¦NàÍF3­^µ¦Ã¶—†&ã­…F4ýSkîƒ0‚Œ<Ç ²²R¶© -ôÕ͹¥P±L¨©ñÅ‚AVjÌ—‹Ó}4¢÷¢k>pp Ÿô÷4Ø»k!/Éëgø2Ó[¢­¬OÏ C#˜šâþÌ"‚qLM×¾If[ÓÐ@ìS]‹üÁíÕêr¨æƒÔÛÕÎ:£•¦bŽ‘»ÐÎ'µ‘µSÅ*½h´!Žõ— ¨¦1èh)6½êˆA7ôzƒàfN©Zc (÷8×Y¬9ç¡ØŒhs$•Ð ¬_¦F`ÄÝ1VaÉé5 5CgòØ@´}Ñ¢¬tF6´´ —ZAh’yY¡~KÔ@ÜÍ5´z Ù€¦‡I°…EÝ-9;X„²´³$4·h,-2†'[ ¿ ‰AûÅS~¥äÑ¥cxžØ·³[[9»¸ŽÌl1ôQ ûIe9£q˜¤puêí%ŒD«ÊÇëßìc4cÏ´Òö6ÃôÖ.¼ìoÑš_¼Ë²ä,2¹Ib˜¦ʳvÎá¶¢¡a µ›µ•œ\g¤{.k´á|°ý•x¥’)Óšâ™\ËKh‡/.*-ö`çzÐë Y¢„)üêoeÉ€]†íÅ)8~>g;R£úï)oàâ ³ªn’QˆËµ;3ú[rH˜$‚XFq8ü-Ü“bC'{Éâ˜FN¢“¦Oƒ5âØÀ0šrž’€ne¶4è–òä¤ï{SURžE}7É…1"}±FÜ “'º†%.$à\ÍÕÔyÉ]H¥¡9 endstream endobj 49 0 obj <>stream + “õ ´ˆÄ˜‡’†Iõ/þMÐZí¥Ò"è¹›¸8ú–¥›;©7£ÝFrß›ÎiÉšÙMDêe‹áêO=èÂiËiÆ¡-,G›%ÞiÅ8SKïÍ>Ï~¢5[ îiiJ6á9LòUG§#î‘sæŽ%„ÈÒ»¬°Th1Ñ[Áˆ±nn=ng}ßdÈÍN)ɵg›•¢›)~§Ç²¼?&¼„–Zž‹`¸¸^q*¹oÜlŒý³Ó"fËù”kƒÍ‘§r +·G9ó¼Z˜3÷R”ŸÄÔj¥àYõˆÀ)†NF°×t>Ã6á^-oŽjVœh $;FXWe¥ä¾=ÑK(±å»håP;Ë#x¤¸–õš\ÂÄ€Jê¿)±él^nþ•â¤Þj˵ä ø2jÌíc +Áun­’úQ¨Ý™Š†5?³V½±¨ÕÄ]ov¼+<¤Á¶ m`y=7´ëh¾ O£w²ë­O(æUz¡5`ºK¸§6¬¡´´;(&+}z,X#›´äf+ÉKb ¶;gö®–ov¸¹¼ÏÀŒ=+”„'›Pjé³Bµ^©3¦0Ü +‰3·ÚÂgj ô­´ ½+%B,HR¥‘74kI é‚‹ÍA9 ísC‹ôr/PQ­ÏFgÎKéGˆBhU8zV›i§›y-ûÑZM„~Ì‚ ÑK}~!6xjOûÙ õáãödowœúq`é­¾@Ózß y^tXC;FèôrJäåD2·ÍhîPhÅutâÔ>W8î‹k5R«p€Ë"¢fQÏb¹²Û"$ú¨Û†¼)/§.`Áé>`ÍæçÕƒ –öRäQ€˜4¥eïá:ê¦ëvZRO‹¡øV¨ŸVeã®”\Úål)±éëQÅz?H]éÁ`5%Anî'CŽàæØfZX¡6<Ù +Ïø†¿\«wà[µá!è=•”ÉŠcÅEð]«0æÌ1¤¦ÅõõÙ¾m\Ë|~_Ögš( †Á³Ñlc§{D×öA‹€Çô­¤ Ù(îÌ” EÜ,C‘Š<«¡á¡ŸXRÁk>»"…†O6§ˆ›¸KJŽ +¤lµä… --{·•Ùû–¹›E­T Û‘5æ^ö©Õ£*ݳS¤Mn‹@â¢êd4^ï3ÓCkPé;;ÈúÞ©8ãžèØûV& Ôh©Q¼éw¥ä£k8ÞO ¤ƒû¾ym²œ$Ö®•\Ír–è¹?4䪺}pÀ;Ë?éÍœâ-lö~P£¡G•:ë¬Ùå¸L§eY0% tMQÊ¢ƒ®”œUI@èTÛíš—(5X îãé .Þ$+/63̦ +À-=½¡ž†4ØûÁÛ"W& +Üм´¥¥ªà²2õ'6¬".¹,¥°Ä2j¬8)PnvkÉp𠇋Ý4æ„N™Ç£zzâL%´½ŸDíÔ¨H›â*ÑÁJrµpÉÍÝ’%ŽÕ4àd¸Î¤nb1ì †,!d47²^'ÍíåŠ}+µFyù˜]cÁâíÌ.I"2WZq¶…3¢­¸­*YNÍÐÎ \uÖꮥ£ÝlÓe˜W^ n+|U©Ó@nÙ\Ò°ä’¡³&ëÃâj~&9žlÎúr×ൠh«âT:À8l¸ÔrD›ÑŽVËëGÿÒ»žÜQ'ÖÀ:YJÞ[zoc+®‡ Mê¨öY’&åI˜àm-È)k3³ÖpËÁ¬^ËzÌr­‰À|”YjÚ–ÖŸKÓÇjA ªî<ÍQǨ™TNÕs€ÅÇZD6C\¤FŒ£ãÒ‚¤¼{À¾e°¤Ò°˜×ê0t†oÍP}š¾Ó@˜973LôÙ1ÁC‘>p¦¶¿FO/üXN67ˆvˆDÖó(“ó$€ro)±2°¡& ¬$ºå'Òlôçdkh)î95ÔŸ›óhœñšŽ¨Dsôbé,l’c+0Û·Œô<Æ:ÇTj8µ³ÉÓÆ®¡¥–v¹N#À¥¹'á* +ô&P3án&º´PoŽ)R>Däè;›V<ñ‚vR0]Õb VÜ¡àµØ@nUB,Qˆh©¢Å”t„,ZêºeŠ¢Ñ&4Bî#Òdµ\KG÷4³qèl¢•ds ÄàÞà6[z" è’K+‰0´"'ëMP†÷?3þeÈÄAËå$6fSRl︣…hW¡dQ³-Ø–Ú.‹]«9ÇR7êGZöÀ*ô…ÅJÂç7Jî5§ûH3„§ %¶Dg›à$u3 '0¨Á3&[¢ÕÜ”}Ëû]ôÀ +(Q—š")oÙ|jA¯š`ç¥ðºÒJŒ·oéû1´r·1Ù³!˜GÎJð.;pf÷Ø +¦½·ØT¾£6(ˆ%C’h!'®¸Sƒ 5UäÁBdV÷8Qo7‘XvˆËMhy¹lÅ轑ü¾´ð«• \ô¯¥L ¿ã½%°k²™Ç°b¡j¨Ã3? M[‹Ø.Û=“Û]uN™èR3ÉûÜ*ašƒ}ÌÚ"Ѳ™`¯ÄÍiÿ,Ì-¨NbKÅ­œÂ¬“Â’­ ]Á7lg:QxJLV^Ä|Ôï•ÛMá³h}Ñ0¥­ö¦”»¥e¥ÑåÌP¨¾Vó8¿LÇÖ”0ü[f ²ì÷dŸÅ–š¨ÅòÑ@oNL‹/¿o»:HzU @ ]ÕãÂ?ÏKB(}‹„«– ¢/†ªµ*ø3`‘å ¦c·:õê)war³”ÕRZvl¬£oNË(ÖN«£ï ê! “Z–I.½]G:ËÌ ® +²·Øl0ïciE:´ò\×jׯ–ø¸ì×8ž]r …ßfØÈjì ÑríƒÔ>8‘ÄlAªñrêE½KÄÛLJA•ëo»SE3ü˜MÒ€SN!æ½·Qù†uu±²È–Fšg )Š(£ö-³›©¥hPÎJÀj–I“]KÐT\kfÚnñ“TžÒzg jvÁ²àm½ìÖÙX÷s­]ënt:µ #Sª,… Ne#úv¥Gjɱù¤b¸£ÕhûÕ™X¬IÄVÍžÒΖÉâðØÞV›idf±ÕæFl™†V»N«Ôß(Ù GDkÍŒþÜØüÁÈâli°-}%A¬êEj1g|n°êóQ+ž¹Aô/ùXT)¾è˜ÍGßÌ9-]q£d× +âØ¥} êÝI®Y¢åö§II:×·zš¼Úü¹qæ,…[ ÙÌ…æÅ4 „o;Ê­ú›+¬¨ÚaS4H14œ §±¶è¢gítËå h§{ßÛ¢öƒ-ªg S¥a_Ì6[6b%)¬µŒzBG­€zðæ²š¤gŒõÂÌ¢°)~,«§á&NÊRZ±õ¬nEÑù +ÎL˜Ônê¥fÐÊéÿÝ.›ECëP.G0Ö†ŸµlC‹-8ã-E$6õ° Ñ«y…8bÊ]Ó²œ,Jlu9“߸¤4s™¤2eôFɃ³›v†1B>^í1Æ­–Mèj½4¡ nŒÜnp«?Yëz©8€‹y¼h|„ÁUýZ‚®ØM $þõ姬¹oEPÛÐ.çYs±Š„&VFn1Ë^åzòÍl+¥bÒHQ‘"Æg›?7^~Ð÷æ ÎÍjK¹©,…éäv÷UO)R%kµ¹ mNÉ«£ÏêÕ)"O{|-Uû¦î<ôÀ–òÁ +û}ªV6Ôÿ® ÀÖjê_¿Óé`NIm^¢>ÊG «éä ùšíŽÿðáŸ=_¬£ö€Î=ïH5‰mùXn$¯-Þ4‚6#²¯ë =h×õVqzgDë¥^GgÏz¹«n½Õ‘¸Öƒ)¹õvlum\³9¸XÛeï°&™ 2 ÉDa©¢«Jä´ÁÆÎ㇧¤ÖÅ‘Ø3m¯ {úíÉœúÏú˜Ýz«âôûkdëé¤ÕqDËÑ_¼WQj¼9ÊmöÞý Û–›Fwk]-Q]j€;–3ä‚B$GÜs­{›®1TPÒ/ÛªwõP*0Xð{’Ê Uà¹áXØhÒ@ŽÎWEÁº°@½ÅÚÓ¿Ï„…’)È2ª{ƼÞDÎç?÷­m} dµWh2 7`Úõª Ë]’ã0ÏŽ„ÌÃsœ”©Øø˜Ù??Z“9Me"¯eò{‰º“Ì·˜)øûEàcÉjó :±H¬š¿M5*vIúÏû¼¯µ]¬–ð^‘h>Û›xèezåc©⢷›v7 ¸ù°r ;® ÑŽ<Äõ!áLGÅïõ!aIvËúÐ.u5üÔFæ-äÓAX>™jC·Þï׈Ÿÿþîö÷W·W·_œ™ +ÄôG¿ÿqü鳿þç\]×fŽ~Ù~<þ÷£_þíw«ßß½¹Ä¿¾ºx¸º»=¿ÿ×÷ýáWÇ?ÿçÍõmýÓIíÖýÕï.ßþâøýò“ûûóÙ__]¿¹¿¼Åßýñ/{û0þ ÿ÷ð¯o.ñ·Ÿ»®ûÙ/Žù—Û«‹Jþ¬¶{ûÕú£ßž_¿“g¿»zóðõ÷? Í ÏÖ®èÓÿk—GôõåÕW_?l=${üÙÇ´ýˆþ¹õ`þ¹Óãø×Öãø× Œã“ß~þÉõ7_Ÿî¶ÏÕ›úä##Á3Ï>”»/þûòâáÓ»w·ojß>½{„Æ}IQV}x»õZ­½ó¿¶Ñ®ˆÉ‡w÷_¼»¾¼½¸ÜvzäÕ-çžó£Úv<÷—oß]o/*íñgÓíÝgWœSã¸Þòé?_]_nÏÆkï<ûý¶C»}w󇋇óoŸ0²é+Ï:œviÛ±}qþöò?î/ÿß»º'·?+fom#Þ3÷=Ù,è'’óòÏ[Š“±ëß³ϼJŸÝ½»¿¸üÏûóo¾¾ºØúø»Ýz®nw\^Ý>²×ã_`4Íö8–»o.ïÏîî·ÐøÂ‹mž³»›oîÞ^=<¾3öw÷ÿ#Ü¿}¿µúðö›Ë‹w×ç÷gw·oÎo·_šå‹/žyê(óÏoîn/?`”ã‹Ï>Êk Š^Ü]ßÝÿûw_?j­N•‰]oï8Ö§Ÿ}„[ƒ5Þ¾»ÿòüâò³‹ó§Œjí¥ƒ¼ÿˆ±`7üáÝ#»çY„ý®ÈÙjÖÿl;!ÿ³õ\üÏKØÒé CÙq·€{ʲ<Ñ1ðBªÈï®nVOq0ý8¾ÊËÏôL\éÁ´ÚÑ娮‹år—â÷?étWÂ)»"¶¶˜þ±ýÎùÇKlœí¶Hxl}~ÿãçÐt q§òÈÚMâ^ì yeáú'+»~ržß_=|}sù°ýíÓ z}õðÇó«Ç\8‡#t»Ø•Ó÷éžä'‹•ZÏß]Þu‰™Ü?•è©[í/É×ðè‡ÑzÝx´À£´õvÜÁø„ÅÙyÜÑÙÝÝõ§÷——ÿ³u\é‚‚Þím +Š;Ý:÷ûþüÍÕ»í§Äßèn¦o®®Ï·õî“ ·õíKžÐö<÷f{žÛ´ù㨦w÷ß|}w}÷ÕÖ‡×î˜-¯PºdÚÎË´W—û¸}ÓA¦=ƒ½ñjð¯¯E”}±u movüÓ’Nö`Ëï+|÷µÖx‡íúîß^ÇÜ“Ýÿúkl3Þ¿Z[sãTë`gwÛ¾œLû\µáO[ûðϾ>¿½½¼þìòúòâ)vÜòÅç÷‹oíÞÿÐA._|öA>‚›û§¥\¼T®ÅOP½Ø}<Ò[sÙ¾¨JÛh_Ž£__½ýæúüâòæòöáwçßìß™ts^›Ú:Ú·¶Rwlÿ=^üèÖ~ÜvÔüi{•Ößåíµëb|k·ÝÞˆ¾§•©ÜÑw†´Úßm!>vQì=a9v|«lŸ±¾R¶v=ìØzD?‚Ø•Ý÷å“@S_^]_?[týËz}u{y¾5»šy¿»ÛG;yáùCè×ßÿëågm>œß?iÊó»ëÔ|¸Û^ã½ÛåàËû»›í÷~öÁÜ_ÒœÚvHçoÞ\=\}»ýF_x~†Ûz½Ù¾b–<û1Ûí×èââÝÍ»Çá+ÓUš¼òüym[ëI“1ÚçÏAl;Ìõ·žßRÞš#¿ÀMŠÛG=äé²LÎo¯nžÀl?RŽÊ~—¿;é°™³ó.^lfûí‹Kä›yŸbü2®à'pØ®ïþlfï`3Û—YÜ?Ü̳_¹³ûm_ΦpæœyùAnmWìp槨`ì>pæâÕg¶ѾGàÌÎYK e^1pæ Ûk×Åø«Îl?¢}}{ œyÂrìøVyÕÀ™‹WœÙ~Dû"~àÑþÀž°”O•!/´”{\¬ð €´Ãbìo½’ýY‹¯/Û‡WS2ò“ß~þk–£ùüi^‰WbÝÞÉ´'Å’^e•òg,œôR"öÊóäÛVò-ÿ”åÛÖƒ?È·ƒ|;È·½’o¿¹¯„ƒúvo».Þ.Á¨évnO—nåí ÝÒí Ý^›t›†>Zpü• ¹­ÿƒDp÷*JxØDOØDå§¼‰¶üa6Ñ4½;N[eØzpòÆó#ñûù¯þyyýÇëó}þ´$Å­„Ã3çp·Óv•'nî+$±_5i®nß\~yuû蕨S,Ø7—ç¿~Bù‰ÉÏ_¨áTÝÙvl‡š;ãš½TÍW\ÝÅm_LãPÞå%Ë»l©Šj»lW«íòÜûëØýÊwÇ.ÕÿïŽëÿ~U®ÿþªþáøGÏGy³åÉ…lvE•z…wJ>¯•üÜà'\¿/éOÓO4a`—WdÇÅÁF£v=qú±iÿ‚QÏnrwóÍÝÛjÿáÝ#‚ës/$ÎlŒû'¶v°ýcûíó—Ø=ÛäìÑt á%l‡­òHn:¸Óydí¦q{"Âöã }¢•°ë'èùýÕÃ×7—Ûkûz’þøå(_ÁQº?áZÚCâôã>ÄŸŸ~Z!ÂCüù>ÄŸŸg|‡;_ñçõ‘âχøócc;ÄŸgãÛø3ÕMD }÷«'©ž‡˜óîz“vÛAvˆ9b·˜óó„d„g>{RÑñµwžÙþuy}}÷ݶ㻾úêë‡ú÷“ Ýzˆó×v7¦öæêË/ß½½<»»­ÆÅíöÂbñÞók[‹ùw÷_VëåiLºþÒn‹Ä?•U^Û©õÄa½âk‰.¸ƒ îà‚;¸à>TW9Üð».¸§(Ã?ÜnùáÄìùÕW÷——·¿ªÚåå¯êwõÕݯ¾½º»¾|øÕýå›_ÝÝŸß>g?8èž[:ö[»LÏÿçêæÝÃ#7CN÷˜=ÿìܘ·ÓåuýåIºÉ/æýùõ­âæ cg~-fÊJe÷n€­yåí7—õl¼²3cùâ (AOåoþùMÕ5>`”ã‹/ Å>b¿ÏÛÁ/µ'~)Û»‘Þ²+âöàÌ98sΜƒ3çàÌ98s6ŒòàÌÙgŽºnÄ™£žútΜ·eΜp漄„|m¸¤òL}¦ö×þº¦>À‚Üu£øUf¿Îú»å¿øQDÄ—çØ¾†ÂŽ—çØ~ ‡ò;îÜõò¯òr’§âwþô|ݵ9®¯þx~õXíp„îr®¡‡ +W»v„¾š +WO_»~z~I}8Awá=T¶zU•­ž¼¬‡ªVЗíë©jõÉo?ÿìëó7wßîúËO£îÓ+,\°uɲCá‚ÝRö;Ùëë@ß<"‰¦x¾‹m?­¯Õå£;½Wv]¨Ý}ùåÛËìŒûË7O×û&þÀ‘þ¤l„_ÜWl,ìÊ⦗¶Óö +ãKè‹OÉöãK(Œ£ûãPöúàþØSK!Üûiøì·û£-îírpì…¼oRààþ8¸?vI®Ü÷Ç^¹?`Ä=œ?$t0áöÚ„ûòþüâáüú÷wWÛ£Ååå-gƾôÌãºøñCÏ=’­½)ûR´øö«‡‹G<§SSOÿùêú Éákï<¿Ëukhïí»›?Ô øí†6}åù1˧[—–úâüíåÜ_þ¿w—·Û{³·vx»Šiê/ê/ê/}°$ÝúŽ ‡»íÕ­»Ý>¾¼¿»Ù^VðágÎ+®Œu(Œµý*½da¬'èN?x]¬ñ&=¹šÒâIúó»û/Þ]×9ßCWã×·xå_><íî…\ÁvpÃ~¯áաО0¢}A¡m?¢ÝÆ m?ŽG 'øç”18„0î^GãaK¥m¿ÕÁñ¿oŽÿ­áOûç÷ïžÛñÿBªì>Û€O+ð`þÀ[ç`¬Àƒx°wÉ +ÜZk9X{m¾V ÛÁÜG;pë* ûgn=´ƒx0fàÁ <˜k4¥Wg>aDûbž¸×b>e$;o +þï»»7_ÝŸo/qvà^Û¯ò:­uîCUŠÝ°pŸT=`OníÛï +‡£ß7C…<›Ÿ¿ÂÆ‹ŒðµÉ´¬^Ès{»¯«Z+·fÿû×çÿøÕ±î¾9¿¸zø×¿?ÁO÷öá_×Û»ÁõéçÏË|Ê áû²©ž4¨}ÙSÿFÜ¿-õ´µxµçÑÁyú2½~ â-‹ƒž½F‘÷S¸ßPøæ³‹ó'( kï<;Ã}÷õÒý¯õø“-ÎÉç¯=¿+}ksP®„=»»}ûpþØ]}SÛpþÞó'-o­É¾»ÿòüâòi<ºþÒÁ +þˆ±<ñÖá}9¸žz™òë­ ãÂÖ{ñü®nÞ=!ÙžöåÍ[kº¼®¿<ɵ>yãÙÇÅ£é%«ý(ªÖ¯¯x ­žþ‘ªüZäÂJU€W¬ûÙ…¸OV–/¾äü©£üÍ?¿¹»½ü€QŽ/t݃"øV?àí±ÒøÎˆÛƒö´gÚÓAyúÑ”§ÏTDì¯öôBn×åöl½7ñ‚Ý:b^õõÕÙúPüÇö»ç/±y¶È#åv¦ ;=G€ÓÄ—°g·È#ONâ^ì°yeHݧúŠwþô<¿¿zøúæò 7‚ìÓ)z}õðÇó«Ç\=‡#t—“»~„n?úkÙñ#ô©âk×OÏ2©'èáÝt\Õ‡K%wX3úÑ¥þþ,É×ýc‹×ZéÞ2¿mq™ýÃʽþÒN¯÷n¿C‰ß=ò7絩­K?ìƒ|wÇþwÓO²íùÓö;Î߃3`×Oµÿ¬¯¾}rµÏ¶àõÝýï¶Ø€»(8^¡õªË¢*àÓ%Û:rß¶Ô~kà¯îÜÏýíËËûÿ¸ºß/Ê®¬óÃùÛ¯ñ>ø<ýñÖQŽý¯Osj®½ór…ÀÞÝ^üiÿ„Ê«c¶ÓrÜÿ4Øí?ìöòìæ~*ÂíÓªÐBÁ?ߟ߾ýrûÛ.v‡û?DáÙu%î[~“—ò›È‚íˆÎ}ðœ¬/ÑxŸ\_ïÀÒìÊ”|Ï` ЗíÇ\aõ³O~ëºÏsû¦]eRåóßßÝþ±6Á">'Bþôò««ÛéŽ~ÿ Ûˆò§ÏþuóÅÝõÑÏÿóòþ‹*¤qÔRÿ÷·ïŽÞ8¿ý«þò_õ‡ÿ®¤ïŽãñïŽÿÏÿíŽßàÉ?x:ô.ûpÚ ®?¾9ÂO}eÕ('õûXIí½M´ñÍ[våGÝiç†PIÝi)%æjdŸfçóÐÇÓÁ§8ÔC±Rîs8þÛùщK§Å…úñ|šº¡”ÚÃßúTúã“rš}êÞúØyyÊÕfÿΧrÈåø$Æ¡tõ7œæÒ×âiéúÎUJšR׃Òõ¥ŽÏêó©óéø$œ9õµMNC (9´ãNcr„0„”øV¼Ëh(„€.¹xCí >ß—p¼ÉÙÑ—ãܺSWrÉX€î4FL­«½ }8vå´$üZ†4ÿõ¨v°pÔuæz~Ì¡¡„ΕT)ݩ˱2Á)§9ÔÕf%ÕauµÝT Þcî0?õ;ü×cµä•:aXÜ:Þ®«]÷ñÔû˜ñ.§ŽÝǘ°Ú}àú¥4Ô%üàc}SV;ºú,i.e,wŒÁ…‚å.§]tØ#a9\ŽJJ‘å¡«Ÿ¬¿ë0ʆ˜@(mŸöCå-WûP8D|+ C¥¬*%r$õ-WYÍô]Ÿv#…ú¥þÔ ƒÇKal¦çÕ†>Ö+§)LjñÄ’SF+¡ O¤.¡¹³åV:%¶°øh央Jq~¨3R™v¨ƒ©Î[ýÁcöÁ˜•kGëêõ/ððà<ÆR™&w]&;ƾNWåÏÎwäOŸüÀX^毅ÊÍ•‹b +üøP|&Avž?íSŒoå½èÝ Ï„Úéú¥¡Ôg+¡n£EÿÁ!ýiíJ]ºbW|à2×F°M*S:B¶ú±à]mÞÕýV¶ Ôáu]íFmÜ Ü*˜àö«“S矔:©(}’]ìS]¡úŽÃúº‰ØÚªë‚ÄÁÕ'û˜dŸ—®rÂ_1Ⱥò‰¤PWÏ„ŒaUBW…P8‹AéÂû›­.|Bæ^è]ª+! _wƒ'ƒ ÞaS„¾÷uÇ@ôaòëVñ\®Î@¦Êäõ HµÚí>r“U®•Öå‹ _¨Ö ó¶Ä´LžªÍúé\w5cêxùÿ]©ò)WAdí*¯ø>zLVý¨ƒt«k®Õ¦ºX຃:OA•kêpr„ ©õ¥îWÒê¾;Þ0¸¿Ô>©<ëKˆ‘uCO–Ø·:Y.wäl7d®®+#bÞ)U±*"¬Òbî)së0ëšáx¨”ž¶(ÃÐù ”xràX!Ö×zpI¥Ô½ÑË|Uö'¥ÊeìÃú¹Ð¥"Ÿ›uýc9§~l ×~”ˆ™Èõޤ”–ãk×ú¨KŠs¤N–ß«´¾jI‘QJéÜß©µÖ©¸Ç¹£NX«×§JßwFWï¨æ |œ +¶qL‹ï®hô~@ﺋSÅZÇÔ…¸qÂ7-ËbéfË ž&rN5«•nà[޼U_ +‰Ëç,2aŠNV¯ÔÜÉIX§¾ª4§®‡>-›:¤B•:éH|{­î=]‰µ9ãP¾‚ɽóFIuÍ+IØšSýN‚ Ò”ÊÐ÷jMQ5©&“à±~g*ac*‹þÅÍ3ðݾjä§wHŽUìU&ÕÍ£#µ-œnUk×Wzˆ½:Û=æ‰ ´+L œŠ:_=žð1%%žèO‹žÙ™‡_%$Nþ§/‡æ‚7} ™k:›¤³—}k=Ñ7ëål³‚œ¬¹£„¹€¬B‹š4¤$eåÓc¦ Y'| +öHÔ¡«X„ê Ef–Ì`Uf¡j4P +9œOØ´i +?n»Vef>¹¸®ü wXê\be `‘é¡ÐÁ(ŽTì72‡_-BÕ•)„!²A€bBà¢ÓR <ê$qËóDäKNb˜ÿ}µ/ÿ*>ÞÑ÷ƒèCÉuìp•·v¬vØ-ÐCÒoƒñɾvMî•ï ûz(˜éó™øûGrZÕ"=vh¯{ªÎlO ‘s’bÈÝg%¬)·¹›‹¡,;› 29 lرi³ çõqý·ðü¦Ù†/U嬎–_r”ôtðKUàçK‚aWû_YÑ“º©è&r7Ö ƒÖ½$'íç!äºîuªÄ ÇÓ‰)ê‡ZŸ©déú×À/Az÷Ixºîeèg½‰ÄÊ­8Yêï¾/²wpÛ›ïf°…­½îi;ÏÇñÑÎ6Z¶ø|­7p‘ Þêö¢ß«T{B·Ï_é>â¨<‰c¡bÃy,Øô·õ‰’‡¤OÕ|ƒ‹Ê{Î4êãy/>R%_86ál›9?7¸G×=¨ð©Ö9Å#pòÓïêºÈ „ é ît4>«zã²ì±²œêAãïâ7€+†YPøHGs§ZUe†¾ÃURxþÎÓ¦*Õ6įé¼÷øJÜãõwñWàöT¶œ¨7Eœ{I”1®5ìDõ‡CJ¨îXH®ºXu?á“ÞË©)ÿø…¨'Sㄇ"E #Š?væYÿöhá{_8ç—üAýje {¡àíØÕ:å|Ø_-|¶7$ÅH§l‹úu±•A ©ü÷£z8ñÄÔ Ð’ÍÑ©­Z—#Ð:ÁëÊ]ˆÜz +W. ƒ $º_ê†`´¢*ŸÔÓráE#,<í3_üb¬G‹ùXÌØbV/Ž6ÄN–ñ•µÌÅ‘1ŽXž÷l^m«­’ºŽsÜEmtÍ3þíÑÌu¾ð¬/½ï"b ±Vµç®£I +¯SÉ0h0"Y„:Åuéª`¨: +¥+"œ®œZ<–à™ëë×E‡Ÿ‡"H´+Á%Ð _÷8˜]êr¢&j¸ð®ÒU•®ì ¶DW¿µ`¯³£®63êÚ|{´ R,ÂóPWPÌÄÊ{BËC°:1lE5_”ûžÆ3V¡1~ý°Œ?pcÏbó(Æ"ÒA±çi¦!VwH®3@?¤†¹X«<êšÚñpú£²qí_]mŠr,b!«ñ’õ˜Ê·Pt6š<)Å R¿ë2Èæ4¡t!ô=4W—Ĥ¡Ï¼o®‡fY­ZõpSL­ JD$*ÔãB¾Ö@Hs1!©`y8O{™º€Ýqs$ÓÄUîhïÖO‰Dˆj /zé9ß +švØšTŽÞ.pB»ü+V.!b{ÂpW‚㤠ø¤ÈèxF[Ú_Ðbá‚Ä #Úl ÉtËÀZZ„§3žÇiGí»p»Ê†þ;>Ze´ìúÑ¡ÎB}LŒ0xÔcêi„á½ +(|Ï<Õëίۑ¢ îhð•£éÞOâ‘õÔøøN ×ºyIœTÂUéSõPC¾@@ÕC¤ª¦´íC† Š ÒåHO™WSÞÃßeA¥$q Z"­„!l3O9,-?T;%_†Þä§Nm'ï,Âvu¯ÍC{óØß2>x¶a¹VuÞ,ƒB¢›‡Žæá¥Eꂦ¬0o±hH¶¸Äq´ttr)Ó†UŸxe²ž )Ð$¬J ƒ^¡ç¼dúuÑ8¥C“1‹Ø›…A¿=Ú,]Tg±Ë Yg $V‰âK™>pܧ ‹ <ÀàpBä-˜\Ú@ï5æÂ8"Ùxq«ëÞçÔjØÚì'/Œpixh&e¨qL]\g³ÍQÄõPã·pPu4øýŒjÓ°ìEO†šk‡²º¨ñ=Å&«›‘+Uú¯è·g¦~¸©UmÁãò§@¹“YLYý;…¨/4@³ ž$§²WìÄÅ‚0@PÿaœÐE™çª4­âEÛp]’ÙààõG …½Æh»qñT”{¸‹ŠB¯è¼jñaö]g*J¦$'P-'іŘ†žÏÌrös|Tž#o$uŽ£K ˆþ8X«Â†ØNâ˜F›qA'†)ÏH'±;Õ5¢âôS½¸ß‡+w`®AâÇÜ»ÉN¤Åª|œaMòmîÊʤ"Bƒú+ë¸è^?á‘T;öw†ì¼f=Iåt†ºÎ”ÒEhO⣔@x•%&ß¡³ _ +20iìÚm”9ã1¬k\EæÕ†ä¤YNÍÅц \Nò|%.ÔŠ^¡JJ‰¶¢ ÂS±† y’’; •³ ýZ–yæÿöh` X„ÝÉž½)M*${ ¡AƳ¥Åz~l”xP¿4_Ãõ¡ãÑ.ÏB¹ï£u?‰K'½D=MúÝõȪúh›ùeW-o;Ï6°ðb^(¯âë ¨±ÁÌE´Ç$Ãqq´8±€VÌá lé¬t¢¬´ÈM¯”î!zb€/Ÿ1@H«³N™»@§~{´º¹ÎGKÄ)±OñåÑbÉSXrÈ¢¡‹£ ð 9äl#\d«ÿöhcHöŸcdVfÈ…%ºa¢Wm£Ò|f¥x¨™¤Q¸ÂšE]Ìž-©qS°#7k¢ïž¡Wñn¯ÁGtÜ.2çⲄ3LZذ?­†ÞROs˜ë‰í­KÁãwBÂTàF“tesŽA‹œ÷"á'R`-UŠbÁŠ Ì«êaÒ8À t6‚Â@S²S‹†cÚ:ð=Ѭ߻³ÕZ.èbÙ/Ž6dæ šCΘNc å˜á=DŠ TxŒhì]X°$å‚0³aèË«_À¹ +œM¸>£z þÊ-U§3ѱz‘RpçÒO/RQ½Ì7 ®Öf8ÝÅ•(AtNiëüò@–hŠ ?ôÔhAÖ¹+«Ý/0˜÷8X$âÇ`3]4€m²棇/dƒÑVI‘øž*ì{i4ÌS£0Ífš òY(Hÿð! + ½}¦u±¡À x@TQÏR§ <òè›Í¼ˆ¨õÅY,ß|‰™ÖU± 0 Ï ÕäwBƒ•À€ù”;Õã—Ñšç`9zÖñ> @Ð 4$ý·ÈM’2º£ÏD?´¾ÒzêˆCÚ¢ªZYŠN&J¼Giå9I‹Fw«2I =gÜ%pLrs@ +5X°ƒ¬9Ë,˜jñÎ60çlT¢ öõád€#ÈnGÀ‘8Ïç$SˆÒÁ4ƒèˆÐ˜Áx@Ÿè‚` ¤±c…z § «A9îŠÂ‹@Š(9ã™ËÞZÒÓiå¯@<˜ŠÁ_Eéè-ä[¯ …ªÍ0{j õAsºS“=’$²N(èJCªÍYã#­¢M¸¤bg—ùöh¨YnæP(Po‰ü<¬>ƒJ'DV¾êå`”éèè„‚`Pgg¢S£ÈÎ…B˘Y6·ìŸ'WVý0knNݵ. :±’Ä?EeçaWwNq Ñ5ËÔ¦(ÜOO·÷§¢ V1M}Ø…AMUq}#WÌ¥®‹ÎÝôkÛˆS1bv°¸»°M8äù4}¤iÕàª"óØ@¼g¹*LŒIp¢üî˜-‰ 2÷É PúÒ]Š~@;††ðôƒòõÉAHOŒ\"?‘0«±NDNR =FÚÏÀ4Ÿx*P„̰ËfÀo–Á5Dáf0Þ*K,Þ ’zZÏ HMj8º—˜•LMÑŒ¥ŒÄ~ɘTMƒþGxÔxOnÀ‘¨1š*Ñé êJƒöe@q†`œçÈ‹: +osX˜yY§ ꉮ_à/Ž6! +çˆÃ)&ñlZœÏå·· ràô‰Gô¦ÅÌ“M‚xô2ÓÏ7Íó|%æ+5_K ˜Tåh²³O€’Cˆs äÅÑ&9GQ®£,/3ê¹£ +­VêÀARvq>5Mîf4ŠxŒºˆFâ–Ö1sLä 5É•¦É×ë %ÿ‚‹Ô†àÍØÑB¼—-—°A;¨GA§Þƒˆ/&1j øl¾p™^6‡‚zÙa—uPD·€§!(€oŠê":;šPa„ȃõy> ‚&Cœ >?MzÃ-zÅÞvÔ ˜A†ù.YŽ7C8²ê3`ä·G ää:®r†»<[LÒÇAq!U¡NjæÞ…!!ãJR ƒ`Šàidz¯2‡´,0/ \ÌEݲ +¾r´cŽ“Bè€wPP‰é#‘ƒÞã¤ëÎfD2ÌÀ8Sf9BdˆÄ ~€–%J3±’п˜(FÿöîÈÿ…¡dq-Vy)?@hÐ׆ÄãÔaú™$fÐq9Þ[!ôth"묎 ³ÛÑ8ëû%ôâh Ý€%ñÖ 4¸€. ‡@¶‰Ã4¨#1jhEYÍ ^xi[ÆfÐ,|Öá[ €×‚!± sž]0õl=ñN¦ÿ„h@¨`•@:Ñͺ€,áuTÓö´ µ AµDYÍà1G@4K ÍŒC >”D‚N $Ç®£3øÊÀ±yÌ¢• '% ÒüaÀ/¹™6`h¯ÍKÔÁ› xºYz=ŽÀuNk~æ[Ë õ2°= gJܤŒÏ á!mƒ»(‰¡ ¼x÷rÍ` Š5Ì A N•%P a¡DPî! +{«èÖÀ +õšv+z×€Àl$n„q¶žé¡XR®r4„iQ }E_,¡&vXT"ø>KÆH•-{˜Šˆâ¸°:j¼¨ÙS«Q¦5 IêUž¦„”iÒÚTÊS”xy±×7U•¢¬Ïnd%úSI‘#M~DÁ A¥cLư’Aºè|„ÍtNæGrg(p3çˆñSqq\¶qrñdÄǪ8‚ ¡©°n–®ž»AÚ“%h!æ¨kPýÝ…›ˆ÷”ŠUá„gÍÆ‚£’J+ó@.Óñøä„`…rtÇiæÝœQaþåˆUßåãŸÿâøoÿ[뺒ªd€œºAœzuÄ´Bºz¾Ðïá… ²×ª‚CÓœæ¯HìÎIÄã¦pÒ`…+»Eh¤YylœH£P›,´™ÛC•ýøŒµÒúžBÁáXLHŽ&*ö¸fF‚`—þ4’uØÚ™HàÐUEÌœ 3ŽÞ‰*‘àåÆüÔsQ,¹º± +q UÔøAÓO$ÊæÇA%JÀ|ŒámŽ#6Õ¾~}(è¶´Vaœ£œÐ¬•SZ9qš 9™ #ᨔ5’õ¸54gˆRöà&Áí š™¨L"§(Ŷ¤2¿C@@DQUÇEOIYµÆÉ‹í©ÖþjÃ7±] ðY‚ ”O1¶ŸWíÌGduèA£‘’ô¼ß²gbËå˜K6õ¡žKòb’ÖÁ<ô1/þpȤŽPÈ !M^°?[³«å—ðyX’Nr=a²Ô1¡ +ë¥:ö$\‰½Ëš$†ñ”FÝÚM_Ÿk_Ymü6ûäm§›Ë´p$P1EUJÐjò|b’w†ojᦠIüèÓWí1ûÂjÃWW‚ŸOŠÍ©G`tŸD²8õk¬&yÏòdÊžûqVmú<¬½ÛžÓO¬–_Õ®&‘{»"@zàÆ:*í)T\SM ¦¤ Ó9yÑžòã,Í¿¨Ýš—æ|!~'ô°šýÈ-ö”“•‚CnJŠª]¯½(OYó«åÙ DˆÄ[*ÙKŒä¡eWãSA¼zbÎ É{öµ¾Z~½p,ãÆL>Æ +¸wÄ f.³Õø”ÙÆäý8§u<Ù³öf{Ì>°Z~SÄ ë9†WXbï†þw'Eœ€*Wãs'ŒŒÉ8œeà¬ÑÊ Šv{×kŸXmøìŠõAÄ•t"”iÖ†lU{ (ÊRPusJßùø–=ÚîžK¾ï¥ /œ¯4LýÏiòØj|Ì+\í;¯)â#)™4³ÛS­ýÕ†oŠ26¨ö—£Ÿ}þËOîÖj¢ÿìó_ÕÿµgÆzÕRizCíéß^_¿»¹º=¸|sü‡ûóÛ¯.×ÊP73èï¯Híºõ’Ô€ î‹s±ÓŠÏF«z(3æð/Žw¡ãzùA OLáQÊÉüÕ“eû‚Q¢½>þ`êÆiàö‚­WÒ¢MŸùô‹:?ÿË-*ƒ¿9þêþüÍÕåíÃqô¿àÄ ˜#™%ûÿO¿:’ªÃêË®Š=ßó9n8©¬žäsÕfgQ¢ã¿ÝLß,Û¼Y`íÕ3óÓ‹É«ÈÒFa«~zmÿ´jªp«ï+áˆ6𤄪ôÈ+‘œŽWž86‡š€c|*Zã§ŸþùÌu¯ŠÏàÚÊð6ƒwÐ)¾ÿ‰Àÿ0lÆ´àQòýô¸®¦;yŒëNŒíN6Mq‚›^=‡ ðé5Æ;±åyäåÔÁÇßc}:ºO¼nÛ/’…à;Ir&ïK€°ôU°—†@ÜG^B2¹uÎcfXìÿ"Bºa&·œ˜¶±ß¾C YÌkå^Çÿ•·~”Kæ¡–É}Ð:Ä$Ù¿'I"C#¡1kzh°#÷žáuiEèŸÖŸr¼öÇ“ùÛ'›>q²èÈÉ¢¯“‘œý‡ÄÏÇ-ps´Ü46Örcœ-wél·~v4Ûûó775¿èÄbûN†q6ÓJœÕtÑæéš®yìFWöñŸˆèèñRu$Âiz”ÐGs›ð/Á˜8·ã¿}²Î6šßñï^³<|['ÖÜù”þìóM©ýgŸØàë{OþÏ>ÿ° øÙç·8>¹Å%Ñï·9ìB¥j]„?ž?<\ÞßþæŸßÜÝ?üY/ãùÙçÝñ/?½»»^æ· þ绫7rõÑÓ—?Þß]\¾}{ü§Ë‹‡jº\Ïm—îɶ kÞ „¶KzWM0œR$*K™Ý4¬ýî«Iœ²”—ðâ šPÚ;1L•Ú)J8;"¥K²"eF +[M©µ:ý=1‚õcò»>ÏöÆæŠÓ¤ó¹X½W-ÝR+…Sî8&©öªdð®‚ÌOq]GDðºNŠÀ{íØ÷¾Ù€Ûbœé¤pìG^µšíbüÐ÷¾‚Ü€°ø€ >>64`:álúôÉcsž©r“³ýÀ¦À¦~×ø´³.oÏž[½àÜ2š^7|ÒDn˜î¦3=ûÓ¯7‹ÉáE|d¿:Ë`@GÈ—˜ZÈ9w(›S jäF.­ËºÙ*=¬Í‡œ[ykË–"ádÓнäÀµ 43kuï=òný«)«Y;Ô%<úŽmع©YÛyô]dû-_Þ²³&f¦æi‰¬ BPa’2wp€ÆÀÚØ6Ây1¹!:å^“6YÙÆ¶°ë„“ «LÛX©8%§¨»£½)q"¬q²Qx3Bo¬íØ›RÚ–!eÚ!#´wØêب€î'Cd/øx_ôw¶¦¬Ö&¿ÛFÑr*ãðÁÞ`{'­Áé<œÍ'fbOÚ†XZ“™«ÓsÃZ7Tþ_Ã6X[CXH‹UœNFÚb%çm­¦æÉ±+i'M”?]}ñEµž6Ú%úXxÿ'› TÙpS(w Ëþ:ä¤Î~ÏZ® Ä ©.DϨpŽR-É#‘Y-ðf•, 4=bãŒ{¡ü~=<°e8¾K‘˜áPE5¬ÿÀAë"d ‚ä—t’ÚwÁÊÞ¾GüR(è– âÛ³z’•È ŒND-¬B>/­n_ФÈ"˜‡ä2÷CRr=CèðÄÝñÉ•éj>8Ɖ£–ÔlÎZæ-Hjxœ Å­™‡ÅËåP§ ·páPW,/ »$úÉYlîÒÒw¬¥/‘DL›ÏRF^KÖ…q¯h Ü|aN O’À¬çŽUVb±¢RNàK +’»öRÖ¬€E¢Fóf²àš=ÐõZ²2ÅA<Á{ÍùæÍ¡ƒâó˜lP2½8!x+ˆW$ý .øW6îÕŸú‹ñöÞϾ>ÿæòÓëËÛ7uK~ýÛ_Ë.üùÿ÷ÞGÆ ýóOV«ýîüáâë?ß}zùåݽ= p<|ò§Ÿ~rqñîæOwçèÞdÿ»Óº5Y;SQ’7ØñrÀ‹T{VVïô¢E–§9GšTƒ„Øä¥P˜ì$„dÎíSê\Ë-,Š#KôZå UÅyJF+•Á@@ŽåÇbfyK”Aè HšÍ$•½Ž=ñ’¼¨–€\àZ[ŸoÔ@S¦÷¹ÄoÁC~'Ê€¢Òs$Êuö0)Lýd>jèúÚvp„J¡‚âD 0…]À÷˜´N²¼‹м¨Õˆ¸D*#n‘”KÏRW³F9€¤dõ²-Y]’n#ƒÈÕLn#6 ¥¥³¢%,9¸¼Ïº‹BÜû„Šßµå?¹-X;ñ¨8A øÄÁAŠôçy ‚œÔý“;ã0}C’t¶èu•¤)'uó“Ô£<¡$´ r±#o&ˆqñ°‰Ö(I% ¤rchŠìI‚ØWî~Aæh”;´bðR¶r •…¥¸!“äÀ1ÈÙCÜ¢ Öò¡öHf€Îc* +’ +¦X ‚ç “èäÓŒhVn¯B v‚^'CxlÞã4 ^’‹‰¨wÈ¡‰¼®¦$ªR.yÞ Ä”s ÍÁ+XÇÛöX%γ ”T’›bQœËGA®¾ }êH‘l)[ 0¸¬ +0‰‘¥Dê9%b–I=,¸08'Üp¨1ÝÖ +VùMçê eä'⡎Àî%¾±žŠRµ¥íxcœ$ÛóKåT’¥X÷±×8”,FK¶—%6P¹Tºc³¬ê$uM¡<õÊŠ„ÆcJ†‘ã"êrP²­ÔK- ½¯Ð±ðËñ‚íÀ‹¨ï‹0^,”N·&°rc2|Ö{ëœrri”÷/ªétQà€$yVÓ–dLºÆ±»”ÇñT^DM$-sã5É<ÀÝ‘õD0Ö’àW/iƒX(È⬥žlKƒÜ¬21Uqkë¼ÎOò9;9ÆqUp’,ÉxçD‡R[ÌŸ“‹Eøx{œÉÌbÑÈqBõxw*Õ$Yïj ó%)Àìx±Ë€af' ¦ulE>#%E.FZ5`üÌB$§—s¸O¨œ`ÑDãN²Ÿ xsbá©Nå¢í¤®TZt.K è^!˜6-Ê2þ†yóÃD™€¬ +¬ÞÙžEMðzy Íܱ&žÏ^å’ R€·“Ëê,Iˆd§b[ƒÐßNsïP"“åf|fD .!±jXAîHBáîaINÖñl¥˜©"u`Q“5s¤J…LºÜÖÍ«A¢n½ªÜ`•’”ÅL¼YƒÌè"õ™Ã:ÝÄLvR€§ ùàY)g#7ZÀÇE<“ëYÛ¨ Pµ“úï<Ô«üä%W¬Ð#gµ'‹ ©¹hõŒ§R³a± +«1°^–—LP0¢\‚옡® & ÿÊiëáÀŒQ0"q½CZ:® NUD­xåvŽ’4´l7’ͪÂ͢ȽƒòXàJx‘T’Ìèx" œ’U¶{Aù; 3•k‹RM‹…r3k½íœ¤|h]R±ªDQ÷Y5œjœnDÕò¦º!Jbh)YëèCÊŒ™"^‡@Ĥr{8©³à:°"‹D°.c‚!2HŠR ø®ÇÂ9šµ…HÞHµ‡J/Ó«¹ŠrÝ”ØPU8£µ³|®ëY?ŠɈš±Ø5ëKóæªDL$“€00ÏË%$‡–¥%²£ªä˜Ä î‚øÆ9S.z´˜ ß((Q„ygfXöäÚÊ5’E™¥²K¶ÓLîg‘‚qH E™*p¦À°Ü­§ÏRWäDu9\Qî¬"žÔ>²òÛÙ1ÚŽ“|!É`×Bé‡B»‘gq ¶>}Ï Ç¢2‚¬e÷s8-ÚÀ,\—D›¯,%e¥™ 'UÇJÜ·«K«îÓ«ZÉÃ;JºG¡]§ïUå£cëÀƒ¨¿r5óÔ¤–•Ü¿Gy!‰¤pòÅæ½Ô!ð¼àS¨%I¦Ü„Æ×Ó̬¾¾c¦©ñͲ-ÈŠƒÅ{ºêÉR—¼8QßrÿÄdÁa|¤trÁI„¶:5k’*…dD”º£/* CØ,Z¬™v‡äú°”™ÊAã4SÊ98Ѓő¢ !„2O’ì¥_®¯‡Gâp#a`­m+”Ì;(ä’ÓùxÍ”j +Q3â%N¦ô2@ü`ç9 + Æ3‹ZæFl$(°ƒ°#³™Q=ePþͧZÝFÒâ)‡=ÏÂÆ<úY„•”S5œàÍѼ{¹ºž'q×gˆ•—ÿïº>臤„Ü ):pnÐÂÒ8[åHfåA¤°´î—”nÔₚ;zÿÞ#På~µo¶’f¨’¥ÀC–ƒ¸ï¥Êá:Û‘=Ì;Ñ`K7G,ýõUô¬–XDÃb:x©s¦kXdU”’РŢ½gV””¹ Ñ¹÷‚©ý ôØâ·d@½I=3™‘è˜ÈÊDQ– +#cŸåÚážס¢”gvvËé½Ü= Úký÷$×kõa#ŸŠ2:¡ÀM5OK2)¨²JµâHû ´«Û½Ü×A‹BÔ"LtBJ€E¬ÒÙ¤èo¬ ¯)³Qé{:µ­ìJL,ï˜éõ®-êóCð­è–ð¢U鎽¸‘pÈÝ¡]¼Ö"bùúl;¥]aQÉp•¹ä$Î^otçç)3½¾Ä&{°´# Ù³t0+%&í!/LÍ%ïåb —åO@ÉP²)GÃY;lïÈŒ-IL*ƒ«Ì8ˆŽÃ;¨Yv/ï¡"ˆøAÔS¥p# +-dubÔcƒ^ ž饤 +¿\ø-œ§¦zòXÙÿ’… +L¯—ûKäü/R” efp×c^ +Ó±\«B 䇪dŠ«vȃ(¨¾Œ‡q/u¼`dHíV=ç¨ß$HL!‹Bzñ TðRû†º»×…] +©ŒØŠà ÍÿÚîQWìÀJbzÃu@†±Þwƒ½šx•¥–Ýraα×ÛD„%Ç÷m¯ÆnÑ”[GžÏôa˱˜2À²ÇT2–•±ÅNqz…õài¦Â­éÌŒ½Îi'ÿ?{_ÂÐT²,üýþC8ݧû,®ìŠ¢"à¾M"!‰I˜ï¯ÿº–ÞNBÀ½ÎÜç»ïz¡èÓKuum]]¥8•òbÁY¹Ä :,Z|2MJÏ9˜|‡f,:kÆZ!I‘Ð!{FKº*MôdŠó=ÎÉJ§¥—áç•äš' ¾¤‹$+­p²¾yª1ÏgÝÌ$ým¦òÎÀdpäž·Žfz.lôº¼ ÔTPô¼˜!=ô´`,¾.ú”|ܘ™ iœ—¢ê袷Ú,<ÉF}iö©N$Z<`æ¡¿„^ú"÷g< +%å9ÅSV(|}®ñ¡+%­¤ä)A¥Ël\³@m3ƒ>Å{®úmtÔ4 ó*|‰¯JäÖàäï¼"×,†ç¢s«ëXw}ƒòwBQCrÖsRgÌÖÌsqJ©‹¥Ö‚Ö²IŽzë–×ÄÙ €9{åÁÝLÙüèx=VL¯×Ù'f?W¿¡¼³óç8Õ—†Í¾õ¿#?>˜©ÆÐ-.ä›··“‚ÃõkŒÞ_~“—S»ýÖIíq½<¨½›ù£5<ª•s;íV£ùn6ºîãàÛ‹>žJ’Z‰I`)½tðë&ýŠÿlNU~ô:ü@?× %"ÍK|onL‰åV^œ)žÎÌÛm³¨Á°x|?‹˜{õŸ©9ª<ˆŠ»y…®"ø‘ì.ÿ#f—€‡ƒ ,Qž8ð—â«v#f0!„ËòÌ¡çNÕOppÛw<"6~tƒgxÿƳ0³”'0E/ëY#KãPhdÛq<6~ô#kE7¹ºÀ +ppäË ³…@ŽÔâlŒÏ§<8ªô4¸í;?ºÁš!)Å“€( ø’úcüv‚–þ™ƒ+<npÛw9sp̓ Om©§¶`DQÆ?ºÁ¤7ÃD´†©ã½yªSÁ™JH¯yæà™%u7¶ðÄ ˜G?¹‘Ó¤(0TŠÒ£K69{Àœô$æ)Ì¡ÃÜXÂH\¥±¬öh–˜¦ù¤Ñ +M¸å9’rcˆ<úÉ gÌË ËáŠÆ—pE$Ô¤ÑJMºnq~YF?Ùñ()V0˜Px΃*o¶´†I~@iÂLü)„IÑóh4vîüh¸D›?–ü¬ƒ.þk|o„Ê_œÂ€^åü}-p`ÀSMAé_p62åd÷$ @è1–oDP–ò§”‘€èŸ`f¿” À”ÙAïœñ‡³Æí ¤‚úÊ‚j¸…ý Hœ­ä1©‘.‹,ú]q¡Qš?P ‚z>µ‹Cõ¨€›ÌM‘*;mje…ÿÒ‚J$W4N[јdwH[Ã_²>H„³ítNí(ï ¡«^0Èî…Îe¥¦{Ã!(CR%GZ•PîÓ/¬¨P-Z Ê’Ü‚ +£´å=¨4-ÕìŠÞ•¥"P¡™žÐcÊŸby€B³7 !åh’šûÒAðCH¥«Íp'±4? \Q.hM¨Æò—Ä­žÈNñ• Mc…RÐÊŸ:`¦íTd·Póý¢0_B8bˆç&éK™IrIˆ^÷Û BâO©\]ÐR~IÂ.‹„rÄÆ±Ò 1µ$‚ÐÎÄy¤vK5R¥š·% ˆA]°ˆÄžDÊ¢ ŠïBrËD†,ÑßÀ¢´‡±Hh]”·A`¸8£|%«í°JôFmñd1âRû¸+µ;­lÔ€ðR@é$É’ ag½Z–vLÅ;# φDÆÈD–JUѧÂñ4J|Y'À!©dübzByƽ±¡&muÙK(Øi `"™~é§ßœ2]âuœY*HJa;Í;ƒ‹‰È17j´T¸4a"¡Ú­ðœ¶¯·BúüøSjt†rg)ñAJbAƒ*{xK7]ª +lž®p$ï‚ÊTÅÜ!+SåÏLª¢fZÒ ™ãÛx—I(q”5þXÆå–æ¶7ªø;"D9 hYFªG™°Nè:&È}]ÃP¹Dz½ó‹Gš–tÉ&ühÓlc½ä«§ð­õÅò)—„Û“p7r8X†™´ˆaqtR³ÿˆN‰ À’¥çkÈöòÔ–ûAVþ~Qøª>yrŒ"-=§¢ð$ú˜.¹qˆ”ù AœJá¦yÊ–ñàU®+/+]:Žå`ÒÊL*ÿ  „ùdŠA¦·+.s«€ :ŠIC†› Ëéd™z ];òa³axógÙ(#E,&L)ƒ¡¾•ÕÇÈñ 'ûR*•@ &J0YÁä!ÁF;`B~a¦eåv¯P4D§Ž5ÓÓBØ]ྠ´&z%®Òƒ,©¢3ú´µ îã[i¢ðªQN°L[†•ÕqMiQ…k÷ÀL[í€1„.lRòN%Ò¡›îï¢má³nF`:];Õkwž´ˆ<¥ Ö6óf™º… ¦Me²„÷è¢l{/Ž™¨![V› @*” œ„Ê(aaE+-ˆ?¥zÏQ;)*}IZ‚t÷¤º••©áÕ - ãÈ‚ij•OÍü'ÄÕ7Œp§èàŽñv,Ø Ð‹2Í{¦œ"̇+ D¿v$@âOù'¨FA’îj–ì ·$‹ˆ¢BÃV[h]qÑÈàD( +ÀŠ“¢»ƒø8)OµþcwLÜTW/:ÕŠƒóñð[EãjqYVé·põ–1Â)`?àIT$«ò.E1Ûáa²ªP´},¸Âä¨vbuï±ÖŨ¡ A’©xtÀÕ!Uåëç[”XD 4yIâPîÅMrR)²ð‚ÎX,Y ƒ–V("Ô” %¦¢'XDñ +¼Lv''”ÉŠ"¯âÉòÄ>åÒ«¨ +B7"-B‘±ê +â,?Ö^6BhN€àL©Ä¥5JV‡Å¡¼˜åNcU #SµÓº‚³ü»è€_=…ojzs„ìÈܪ€¤²Y (à$q<Šé(gY‘Ч^îaYe#@9sÀ¤(¬g;Ã;·xP4Ùœ#…'GåÉÄÎ$ «`i ²ä—…í,9˰%àõB8ÕE‹g¢æ©>M0cÅ–T°®$‚#é™ýÒvfq©°BTŒrÅÁ¼ÁÖ(Šþ7PQ9j +¥ª…µcX–+ÏóPÕÈà᪉‘G€ÈF,Øj”²œ†òó@¼Yæ™ê§,­h$Εq0{ˆ<dËÞŠ2Ê„•Ä$M¯¼†Ê +1=ž9Y‰ãÃÌ-¨QA yõ”L¶ +L±ædØ#ÁDe¿Tê§çiBbrd\†å«TÒk™¾Hñ@‡<Œ@‰QLî€ÊV`~ùpÃH“‰63ò;ãåÙ(™I¤ˆlµÔÂ’„kh Ï*°Ðy4´õƸéA†ßDU‘R±µp±Ê‹%!(4Ðq" +×ǰ. +, 4 ì€"ÞØ`vûSŽÀ‰ÊÏí€Ï®P#@tVER9 hX2“‘ž¼™‚ pidU䂜x ÃíÌ#Øn„››Ý.UVXDJaÊ15k© _€"{_QèùXE°9í ,ÞvBˆåÉ5—ŠJÀÅ]ÍU…€+=£Hâ}qn‹u9±lå6KhøQ¥NX?jý]T‡¯žÂ·weðˆrN•Áµ”_Ë Æ·ZÊ&ç.Ý­–¢ª»r·ZÌÚë +Hnï ðŽY ˆÏAâv‰›5"ÈŸl§a9>ÅÇéJ«k¢º®Jw³‚ÜåVTÚ})’ÚuâÃb€ø.{[@¾áRT@ÞTô Ò£Èù† †ÈiÂIzô4ÄÝpYuÜí `-!¬%NϦ« rûR–•v#×^p)ößÁ¢Ü”®‘´Yö‚ @%MÎ^p$åùú .ˆËi{Áe /ñ—š§ôð°Ê{¢ Ê_º.ÈzÊ(·WWöÞÉ‚ðSM±ºq;ªÉCÐ8Ì™ ýÜ{¦%#€hK"âøŽËŠàŽ+Ú;.ì !|/¡±Ê-Bü¿ž ½ââûEñÕ•&ï€YS¹Œ›Q#¹Kº¯“$E-¥‰Ø.Ðù@uÁi¤vOQ7»á²*“*Ü —b¥@ÒÝKàë +i¯m¡® 0¾àR= (JìQШš[#ü¬¨´#;z+iš1ÚÜ—²Û\¸ .°C!$MG î‚+Ú .5¯vµ½B"Ó±[ ©äv‰Uµà½‚„çn¨èÈ]p)~*j€‰Sƒ1úAî®”ŠßHfÁ‘IiÂþ‚ ßñΩÜ]\i¶i,ȼvŽÚa™nì?š¯q£µjs sÆßpiŽ6 {Àü —–ö†Kó]ž*Ý —f] néæKàø¬Rkvˆ¯®î^qQÙ¿ ÂzHrŒ#VI%Þß‚¾qx¹=5Êö–Z³-¨|Åe¤6©M’I4¼¬! +¸¬¡"yt—5ôæ Wm5?>#P  ò‹¦2¸¬IÐ …S'„IN±cAø)¼]¶ˆuŽ!Éñ ÑÇV$ZUUb™/ž‰ÝaÈ í> þÒJ«ªç +`ì<£ÂžÌÕ…1OYD~‚9¸uØIÈ<@öêI6-ˆ¿$ ×íÒÑF’·EûÀ»¤›i $N-3Ö<2)TG7ó(ë…ª)ñJvŸ†·ÓÐÞÖ`ÕOf ¹Ý,|‹Š çØ•¼sd°d­¯pNbi}]×$Ž÷øû|¯~ ï’2 ¥÷µ4o”HaÛ¹ z…˲6^Øx uJa98Ç6#Œ{—°\Ö_ØÏܬõ…èr ƾi‹7?åXÔj¼…‡R5á/>©H)ðF¾±I©v4‚øZ$õ:¿±*·6Z‹d‚l¤Ô¥õ k¾YfîÛqmÖ°7|âH£¦nT«ÄøÉQü.!ã%PJ»Tþ²°JWˆÊŽQAVã:íÃmë§Eè¿´â×ÝÙ€³ZóQq! ™¥O{g‚Šr@OyÄD#úÌ2^DHǘÍ$¦÷Üѱ;(ņ@t¤=r ?VÁQq—6øF=>ÛŠ5õ@v³C×e/m,$¼´q0«ÚQ°UÀš`D>c¡&ŠO×Ã¥ð!Y´pÁ(ƒ-åOiŽÑæƒ3@Ê +3V^®…@‘(±w¸S(òH†³ª¬P”?()çepiãAá­…:ÿ°òÉ_Ú ûŒD¢}–ˆNv®âUñ.E²Ù2 +¤ÀW@áÇœ¿(ÿôº¾¢&ä¨ÄFê┎\Z³9¥ˆÕk“(…ÕŽ©°@¨Ѱ«”냎KéP_™Y0 Y@îç—Q©sаûƒò[9OHð£J¿‹_æ«§ð­ý26ÅLšš¢Õ@Ó<Ð!, h€Î´çÚïyp!—cvç݈nçî÷¨f€5bZræfNÊ£+D*¸}œ¢ç‡pWï”À+ÎEŠ—™8e{~0 -Ìž2 +N£ºSK2²GcQÒ¢ÜßÌ車¶†O\¸øVܬ1¦²÷ä@Ió(”…2£¤YÝC¥º ÐêŠzSa ˆÕ1Í1›ièŠðhQq;Öî4gç@P†º:ñ§ø|²Ò®`ö½‘gGM½rc„³#®!ã5óĮպÏð¶6 +¼šLªøÛ?)G4ìˆÆ’ƒ¼oʹ³œ÷×û>HýF: mQû£gµÅ$×ZâÓü84 Q5-*¤ ³iDòòŸëè`À« )*§ +Ü&:8jŒGºþcZÜ%å ¸JÁý9OOI\0sêb +àcîõeæžÞˆ‘`^”Ñ©²î hYŽ…§ +*gŽl?=´ŽØ±¦Â#@4èþnÆ¹Š¤L…Eª—š“g{™âîOr*² Ó|Sˆ;È·&¬„|d”mË‹OÍ=ÕøIhwzB ­ù]@ô1]>JжÚo6ÅïJ$¦²Ú¹¸ÑA[Y¬ËlÆ.1!ƒý< =X)¤œt 0Å¥¬¤.dä)¥åΙâ!3ÅíIÐY’j‚A1ªÒºDìä¸8.yWàI ùœžíœVŸ¤• p¤ÇC¸3N… ø)§Q,,Eñ¯hC„]g>ŽØÊ¤0ܘž({cÌD;õê+‡™Ý Ñiö0ô2¬d²EÊ´ö åU©Ña‚i’D™ˆ|Öøžr;÷̃L8 g§^yö18XØÐV2ê#…– ÓŠâ+(Sf¨ Óõ^¤FcÝéø„{¤„a)êF€TF9¬D"+8õ)‹èèÔ§”!9<õ)Kw\¬ ­ð ‡”èŠä(¶œ¢­HÙ±l™õê›zU +Aî@Uh‚èt9ɺì":qnL+GB †;G“JM“®V—!™ïûÕbÜ'àÎÝ™e½ v¢°½¥–ï§C-öhgÝüþs^ǘ è:!" ¹ Ó &é :7»“T–WÒÅN/ql6Oì*èÅz™z +A'!Ð1rÛ™Ep0¦ß‡`nv¿À³_áÒ* !9«I"E¯ °(¸ì­C^I7ç() ¦`ÏTŽøžU Ç$I$¨ø …µ«ìà$© úÇп€~L¿Ï{쯞Â÷ +\‘z4pEê‘À©GWdøÛ®H] \‘z$pEê1+q»ÄÎ-\‘zLàŠÔ#+R®H=&pEêjàŠÔÕÀ°¸JB+Ò?Ͷ)R®H=&pEê‘À©«+h\ñæ¸"õHàŠÔ#+R \‰ÚeŒÜjà +FNèJàŠÔ#+R®H=&pEê‘À©GW¤¸"õHàŠÔ#+R \‰ÚQàŠÔ#+R \‘z$pEê‘À©Æ®Hÿ8›W¤ª®H5&pEª‘À©FW,Èzcʸ™ \‘j$pE†o³9pEª‘À©FW¤¸â¼\DHH[j$pEªÑÀ©FW¤ \± GøYQiG+Îûè‡R®H5¸"U5pEª1+R®H5¸"ãçʸ"ÕHà +詹 LÇЩƮH5¸"ÕHàŠTcW¤ \‘éHàŠLÇ®Díè®Sª‘À•h­6pEª‘À©FW¤¸"u5pEê‘À©Ç®H=¸"õHàŠÔcW¤ \‘z$pEê1+ҿͶ+R®H=6põ©ÆXé8ç a<Ʊ•1kXK5b¥£-•U!#Vº´/õ£ÎªVºTc¬tV¬t¤ÇØJ· ÈJ·ÀÈJ>&+=‚¬ôÊTȰ¦l­ï`ahÔJ÷x +:«Xéέ•ìµÒ£$+Ý‚B+ÝÂÚ1 É&´Ò­ÿ(²Ò«À܊Ί•.õˆ•n]T‘•ÀŠ•‚«b¥£¬j¥°b¥ãŒ­tX騿ÅV:žªØJ· FŒ”Q+½ +$Ù£G¬t6¶ÒqzU+—[鏨ØJ+Vz€bk¥G[a­ô`ˬ•l¬µÒ-(°Ò#š`+¸Õˆ•^iHz_˜—ye`ÖFôˆ•^YZéÑjÉúŽpâA#V:â8¶Òq'b+ÝZ%‘•í¬[BÕJ¯YéñX;µÌYÝ­ZéÁ°ÖbÆéU¬t'żõÐS±ÒÜùΪVz´ÁܪVz°«Ò ßQ+½Bd[Ͷ +±Ò-ÌYé9è-˜äP ªobte(;)z ¨;ÏõD޹ýT~ÑYë§>EH$´™¿‡­þ•øö¡ X¸ +r{K]SÁ²©®çÉŒH¥šHÁ_:K]3O©µÔ!y+Êß”ž;ˆî¼d¿Ä˜·¨]îcg|½Bб†ÕÛtÊݱ¥®Y§†ॽõ g©@¥Ý—”íÑZêl@Ä[êÖèÂj"·íü]¥•EÈ–:¬ ¦ÔZêš³ˆ4°ÔíeH¥N5øäny4/Àê°WRWšQfc‘:K]s, ,ÊYê¤/­¡î\)©3Ô5:A3Ô5Gc}(»/tí'Rg¨P™QoÞP×üº€En¯=-Æ­žÙÇÃi`¨»Û°e\Á!ˆíg$Ï`ÎNÏ,OL™›ñ£dÀÛé$;=Z;=sÏø¬¡žÑs>ÈQììô ܇ˆg§û«ng€g!.dtK[æ„ýÀž/é´Žâ½rv:\RÒyr†ºæ„iTD…÷4Oè¡®ÙÁòöLÚ—½ÎP×ü®@ÎP׬¸-u, {xgA…9§( •9ÎR×T‰†ìîÏ— °†ºær+JG ÎP€ÖP‡¾»l§Ãˆ<¯Ðvåº^ÒÙézž Ï5q¥ÀH¦KÁ?ÎHçúÃrÞžœpØè¶²;3Jè©ïY¬gö]½lôÌá°Ö%ÄÞØFÏØ ­Ò­3}X=›/PVC±6“·Ñ0µ6zÆî8{l£gVmK‰;ò—Jñé¶6zf·#u¶wÀ¼nP‚Ò „\Äð2Dz)¹Š¡ÄQ=¹±Dêltm³•§ÎF¯ŠÒÈFW@"d2È¥êÒ(d0!d§A:ŽKù5‚ðn›8Õˆ%ñè,Wª`&ó*éUpœ Œë Ç™ÀH]Œ>ÎPa&0Ê *âL`üt:Ìæ$Ž íAA«ºd`\°2H–Ù"3a2°¬`aE~&\—dNï³Q˜·Ùõ3ý…ÉÀ°J‘}ún™g$›3Je̽AŸ%*`ìÖÂck7ðØh,ïDðЬ´@Ÿ Œ…O ,KšF˜ S“#ÐEóÆæô²7&QÔ`¢³  óf!æ£SG5(,ŽÂ¨Az"¤KôE„©™(Œô@5H6šAÔ Å– E +Ëi}Ô`â9œs!`Ô›‘³¥d*Šv¿ä£ Rò,§³²$H &KÞíü°N'S‚qáâ0Õèaª/•”Èy«A»œ·Ñ÷F‰)EœÌ)1~vt£&¬`6¢0Ê +VX¥+Ä +¥•$PZŽÂœòáöƒµÓ0)sŠ8+˜µíƒ³Ì(½{ˆAI9 '=kcj9~DÈ™Öi…à3GÈîXg7:Sîz. +š7Ò‡ ú£âBѬˆO·vDøØ­‘„ :P2èV¹³¸B‹ÏH¹,£#7€i|¤ Ì5Üjþ4Qi•ËB,­*+üX{ñsp>hP®¿cÅ×kŽÅ…Æ’w¡TqhOƒ A +ƒæÐ +ÄO“v FM¥\C +¯›Û.î/Éœq):=qf0z/| ©ÖËrÿr€Ñ=0\YÌkdR„ª¥ÚŽ–_Uf¢˜AéÕdw!ùª4 ÉzŠUÛ’GpÕÁB +œ)Æ9±<$¸p@á:ó·nPLÎ^HŽN¤ä„¤Ñi¶·Ñq¶÷‘xœ[&¸óøð6‚J…SN±P´°jh ×™×6„Ug¥D(«©8å…Þ7GNb%Aø“ £ÓÃûºDý>p +&ÝH‚. ÜÇlÚ ¶ÂwOxê½û˜e_ø»Èû=(ð{`a_WRНH©U˜¨¢ürMØ(]. ŠTi.œëá+¡«¸´ŽŸ(Ù ãÈ”œ08øÒÚ†áÉ—P *>ùÖs‹«µd +<Èè_¡Y_÷.äÂ2êÀƒ\”V9ç-“|Gl¬¤š‘dÏ”ªÐ¼%G‚ò÷²B& äó`ÎÞL?.×ï gÇ2 ^z KùÑ#”xP€:tüˆÒ2áF¶7gù I¥ªãukðÛO)¤"‚’Xwg„vèIèŒaס•hnÐDX¬»Ž×]©J‚oxb +A#!1ç;óèuc†Û`)Âm–WÜ– +r§Ñe„[yHNeô—0äd‘ps—Y™SÙ£Ì(8ô<­ƒ‡üS\ôUbE(¢›!$Nyå3UºD•X¹¿ø òëÜ÷I™ù׿ñíc‰‰â xƒÙeB¾\uÖhPJ0ÌrLIm´2ƒ„ªœ:ƒ '½€ÅÈ|>­À  lðL™ Ié"ûDA%“ÌE⑇6ƒ!÷1p$I1ŸjâR3C%Ú9,/(K6ÖR¬"è`V{CŸ”ƒº|BW¿/R]†õ%h7ÿš(¬’ÒÞÕC‘Y\Ÿ ½dHŒ f{óh¥¤Uô©Õ}ÂZZ•ý¤G²fÑ€J•2ZÞ $»íª~^âŦÒ$É· ÇÕŠÀB˜ŠOû8·˜²/ ðEiý*dõ!!I ²al\i’†Xc”¶M`ÒÿeJ0Ê è‰@ #·%&ƒ¬„eö(!F³Ê‡r ¢hÌ}XÎMý —ì“Î&z´xs pùèƒDˆlPØ| +äGAà!ñ™t´3ß‘EûǺƒ!‡©l¾e;E‰Æº '"Ó+lšò;±*cL+@®ìgž¤¬ˆæò›RXØ$ÖãFŠ $uÖ3E^™yÍX A!Rœ¨7Þ]á¼Á%S†ßÉÔ*œ~ÇÁkÌ;né‚ E4å$yHS© · ¿å0O¶©½Œ ©ôkBSæ“~ öGÅCüâ=Ì+ù¤©C‰[ÆFi!+岉‡£kÁöQ´yDP©M=ä…ôØ2õ“”¡’Ýшbd¥\Ab‚âÀ”—PÿØC¹Ð!‚µVtÕk”‹°^›Eýü1ôóÆ”’„‡üð%&´ –Q ‹Ô$¬²EE?0‰²£Êœ©–k 9X 9<ÔIèÄ´—CìE¬H¬ÔV/Ûl’P¦‹Ð”êÒWDhJ‘ñçt™™L]%9L3 Œùã)v2VûŠ<ôS‚Õâmí3 +»‚ŒÕ¸.þ:¯""繄˜¥—®Pã]¦‰³séñp‚Ç*õl'£éèŒí“[›dc¦¬3‚A…ʶs““¸†”Z‰åÊèqL¨*º•h•` $¥cæ +eÐÝ^á®LhVƒþ&*lZû£¦j§¸B¬V¶x,YÜ™B ‚\Ð å¿„5gÍ}9ÙêGè4*J+ Œ²m  X¯2ÜÈh¶å8„a¤9××Eƒ ö‹sÐÛ{ŸBëø'n„?5PÁ·zþÉrnN¿Ò‰¢ ×<ø)µ}¦ÁU]𽨌cš¯@=pAo”L6 ;B=²1w#EìJÝK„âÞ¸•ò ,| v,› 9ýÊ+ÅŸ}s÷“m„?±Ã7ú^ÕFÆá•þ}ú—dÃý_ÙæoilþÛÈeXæ…˜€# ;ÚI°äʼnG±ù3r!úÔíìÉTLñnôSZL†nã¡YH1½”ÓXL€nn@FŽr`¢™_a@C (‰÷/Fz°í1AÄÔâ +Í‹·5Øð˜b:qsû†Ìáv#¿/ø—Ä_8þ“sMFã£ÏÛžy½~§=‹èGR ì×ý +–  î½í)$ Ú§–~b’JÂìo¡” ›ˆ°pNØDk…ÿÝqD§o1W©ŽZ¨ +^”%’<"2šwÌÛƒk‚ÄàúÀßBÌ$L8tRÜçi4BŒà&ᛨ¨cæ[ê ?‰f„h¾©Æò?F|U£EÃÈ–È4ÞÚY^0=…Ä6J‹j¥çÜ#B"Aé¨l” ++t:JÉ¥G³¶b3ZFã£B¡#ZAhD£$S!ªQ²‹È2ÚˆŽF‰¥BN£d4ïo¬/ý$‹oª]ý×_Ô¾FV^ÝϧFØÔó©é Kýáj«ý×û_j7 H×6:ÃÚÌÒ†H·êÃa³ß §±û¥×œ­Ý0 E™“ãP¦fb"¡0ƒ6˜ûÂv³Þ~\ö[š¦QoåN»Õhî4êíVçð~¿µÿ¨ù…z4Ÿ-w»ml­·Z6Û[ÍþA³1Üùr²×m¯uê{íæ±m-F'ºög¯ÛS :tm°—û§­ýæ€ZÝ2ÿ*k3³µW/§¦MÓäãZgŸÆÄßÕÇeƒCf^˜uû53õ“æ¬Ù³%óßWLºÛêÚáV¯Äÿ¼úb~yh~ød@èL¬½}ŸÔö õ¾Ú‘ÏïHŠ  ä’H(t¼p­5'y( >G¢gß~µrˆ#o ¬TgMÎeI)Ʀ:ÚÊÔ™È*~MFBVPÉ9TGæe>Þ,‡è#nK,|*Bñl øep¶sP:ï² Rÿšåø@M`+Y`™ÊyºÈ0ä?ƒxy,>›A¢ÌÀ1Ÿòh6ñ APœqÆÙÖW 5^xàxJg† ù®×Lï µ( T(‘ð ¦ÔÀÂ× L$¯a +¬-èe¼™*°¯ Ò‡+SD¨`ZM©àboqò ²:5x†ˆní¼$fº2%± l&zðËàTâ^¦óIF—ª’žêŠ‚r`31ËÆVüšÍ ÓJü–Π§¤s„ÈÒ"3ßXêÍt€xܘpÇ4DzpŒ9ƒð>£€B!XÊÕ¬C— Dc*޳"ˆh¼ÒÁ 8ÞÊ‘58 äÊ6´g./ˆ W´J\ŸA%%ðˆüÚ9Äãw< ñòX¡WÓw@÷pÁf¶%•)?Ä¢ +ñ ßcŒ2¹‚àr¬©›‰VGTš‹g˜9`µH,†„\Pd Âá…™.ˆ¸ø¨À,°-øºPI¾È/à~×ì¹²Q¢~¹08•‹/(ˆ_ÙÊ 9”ȱ—xz0g =*:—Ãaá 22f¢ÅqÎÈ”¬ù õ›ã´2eCñN13ËlU0øž5Ár,Yš½ÆG`™æòðµ™O–Ò·ÐÄL&ù©>`âÌñœN&+) Ô@ÅÇXðI©Ëš.æiŒ¢Â|¡ NòbƇ³¬m‚ró;<¡×P1(=ƒ·I)|ìëF*›æšíÜ/'~Çû-bø Üýµg’@¨>§o’2E€Ä|ù°¨RIú£‘ !ÎLòsœ ÈN¦жô«R45 ¼RÓ6{¥9o•Ψ¥†DȦXš/rŠÒp¦MŸù|®`-éu¦éŠ™t¥‰ßP®N bz¥y¨ª”„8S¸´/ô¬SI*³ÁG@š†Èä@¥p\Æ!˜îŽcˆJqê_³eF{A²ËK,ÿÏøS$³”Ä^5„$ç65QÆ!òX/Xу9üˆ"3̤…SPr1=ó!€“¥(¡BI/C¸ÒPò³ý&\ EÛ‡LB%´­Dš +z¾ +¼/åT¼jÞA§:AæGK)TÇÃó™ñ¹„êç žO—À‘ðc˜=‡„'¯€`~yàÀ=5Œ’’£Á‹x(¶ýbä?–=7mFB¤¿dMP…Á$n…0ÊmzhxQ£!f˜Í)jEC¨o.Qb “F–ôPBÃÅ/懅*†C1¯0Ÿ¨„ÊÄR +¬G•åÞp`à ä° 2¡9±ãÔåÇP)mÁ:'²cNªÊ)>Ê)¸+•Qµäª2ÌŽjÈ”È)”¦z£ðIIϺ¼Î„q`RŠ 2:xÀŒ¦³x.¿›T6a´æìw¦7 +¿2_Qµ9”}º ^¬ñy-ò,`  £@'D¡[æ›,£œ1Úf„FeÔ ó{Z B”Ò«Ã604|cލašëbf”7Ìpc€¤tšà Á¹Ö }’RéLñèèÐŒo´™˜0 ˆD€=9jTÄÛQ€N„ço1ÐR1ðíÈ!dñŸ\r@»hÈ”ci$M‡sÈ™‡Ç4§Ò,9ä0‡€1A‚¾ÇÌ/æ(h]UL½à>Kjœc=(¡Çêæ#…±s@-`:&Z0D±2ÁH*£L¨ÔaU4[¡ß ëÌhÂX0P.¨³9$ÃR<Šè»Mñ<y< +3ÖSJj‘Jz¡)OñXÂA-) XÌpeÎ?ðfÊQ]PW¹¢Rit¸ñ¥=òæ²æ·»ã¾1rŽ(³þ›£ R!áLùY’cƒxf;À¨Ë© !FáÏfSiF!âyâë0@=Ó§"ý/U¤,eÊ{Í(—VƯ¤í0 “—Ã7)½¦œ`º¯‚”$Ü1±ö´È5ƒ)12~”’rÑJ …¤_e¢ÀX‘‚ºã˜Ý4šb‚Z(ðØYY†J>€WC -ê €H2j„â˜1 ÇÄðÇêÈÎÝäág‰ÁÉ’ëg`ž`0A¦ÈBÊsPRRQ0¬rÔCæd‚‘W&1K1Í F¤fþ 3—VÂѺám!Ó›ÜP&Ž›Hê<ª¹äZ ÉRóYI¹2Š„^p§pFA» ¥bŠÊ-†ÄËѦÝ}€ý€¶n1†9rØR3œ€§Å9?»†Oø5æbÈ!9@ŽS3|¶@fûC>%ð¼å31Å6h$é–ËÁŠ5 !dô„´vÔ¾H!G…™¬€H~zýŽ9@0‚‚ß…„P*ƒô‡²fÈRè›ß2e¨­2Œ oþáQfQ@n[0Sð‘¢ÑA +6Þª€‰‚µ+IÍ*€ÈЙ$Ù²,8«¥dÁ +F?<«Žãž‚6NÙ$€ÚÁ AsÊðn +ç‹â µc`’ˆÙk ÂÒ—†è´‚ÔЖµäºñt0ðøqMiéX ~`©ROub‹Τ +”ß(¡õ0èÎ|Úp3ËŽªÆ·p)'C–ùKÝ _a7¸@‹”µ L—XàóweócÊœÒa¬LÖDɾÁ0G2D€oOБ(9ĸÙ2±¥A½ì”‚ߥ÷Æ ˆ[‰…a4ø—ô"‹s˜9¶ÄAJ—,¾$³aeJ”–›68JÏbF+S€¹n‚F‰ù"åGB€£Æ×„ ×™À©”)‘cIÛZr¸´¤T¾ ú-µÃ'á©/m¡Â×[ÕfÊTMW£Pü*Öì€VçK.r˜CÙDªUÔ™·ÄÒÀVlEa·…D†*€âPeT¤„Á».*G Τ¢&mH92 ²)ú @£EoDFI›TJÒü] &á5­ »Žê¶€”¬ý#x$Ð\-¹R–=Z䮣g¶†” ÚRôwЋƒ?T¯æ”4LH)>+m]l¯¡sŸ0Ç´À\–®$,x4¾ÄNH}á<­` ¤!YJ[çX},åÚ‚ø Ùœ[Ò}ný€ó  +k)kRùç\?"ᧈ5ã0^ Žå£w¥Ò¡D¯ ±m†ár(Ù<¿Ü*Yp¤œþw_æ¤BN;‡d´\°† Gkbø+I™3´wN0]pA.'2|(·‚D‘= œØ¯À•Áá¦Äª)ج„ ø“ð'lãr€?—Øù#EFùaIßãL:á!°5Ÿ­5'r:Ù0Iic˵-´™p²p»•MWR~0£Ä‚FBJ,'ìQèÒÀÓE)ª +~¢ +=5÷Ãi›&›¦AåÊ °­†^èé4iM§¬ü‹’Ðçu+YQqÃɄ꒥FùB@Âe­m"Å”RïBT.)9:ù7sRÙ`çTŠ~˜’ßíJ ·Äà¹Á诟È&œã¶iŒ"‰ß•0®$·¥ã.­þ°M¦¤¢"¯67Ó;=D4¶XI õá•b=tÁ(9¸Âp8`Õ`?¡ëÝ7p™#Ñ“„^kŒ£GjéÎf“` ¡g1¥ò=z$Ët\ŠÙ)-ÈÊ9²KxH+Pí£îÁ1ÈKV €`:u°•HBÚ¢ðV +d&úz)9nʶ¹Q©šLˆ ûñàîÞžÂw9? ‚g˜[,^³1¾!§Õ1‘ã‘L%f31’R 2ò”¼ƒù‘+ÉÈ,ñ>(èõÂ;à:†ì3|vnOL©B8OióJ.—AF-ôsÌãÁêÇÌp¥sA± sži.¦—Ù{CtVGÌ0 ­$·]³øi’¦×@3"¡VTfÌh%f·^ ³`‘’`뛦^âã''ˆ|þ%Æú“ߤE‰¯¼R>y³Ÿ¿Z‘®•з."Mð#QvB0~P–¤6É™`=˱£³¥[¿½p‚ºx¨q¦…Í2OeÒø+Ð6@"Æ«„„7ù<ñC€ë¶DqŽð#.F)ð†@În¬%ðgkó'ˆj‘Yç:x„1‘)¸¯¡|®B¶¸>Jps—™u}@q=¸6Ë0Í–¢°·ö•P¤2æÁ*àÒ  m”ïŠØëž4LѨSä`çºÙ0‘ẞ惾€5XÀIàIÆèC:Ý•+íHx!iÎl*x…$8§l“à¥\«RŠ"*'×sÐg^茕 +ÌÖæ²ío¶@ߨ@³9M©š&|RÒ]ü…<³\Út¯S@¤Ì)=1&‘PÈô1‘hÈ £ JI‹¬OÚó,9—w€I®isA[ðÓ‚nN©È„·/ßHsÁ^¨ùRBÎOø=¹Ww`F°í¤Èá­%*œÇýç —‰4¸7Káb…8¨91hئ’.A‹Äƒ–Â]KN×o¨×  ܯ 4¤TrI·.¡Œ…¦Àê‚ùÂ}:7A›áé r÷*º„¥‹^º l§îz*œbÐÅÀ¼5¸2'ÓHÔ’ô 5蘞9ûÎ;°æ«Î”žU+È])ã%™†«RP; +$IŽáݘ?!/5±hHö #QŠ„æ‹Ÿ¥¶¸­2¼ÂNç ¾]NÚT›?¼TáÄFÈjÁŸªèŒ› +x‰n),°µªs¼4C2„)62I»@ÐÛPôÉäxåO‹ÍfzÄ–à²É­Ñ©? ÿÊÀz =x!~»4õHE@eäk™×X`0ÖDwÎüJ÷Úpq‰~”„âà4`NvôRªȹX …Ž”}Eéý3Ÿï=sE×í¯DÝb˜©Ú[rÏàûƒ›õ4ÿ øJ¸F/ñµ*èf´šÝÛn34<” x§nŽb1OoãH(€»*B7/^£ +`曤— |'>“\H6eøP$™Ã˜^Èüމ” -z8 0 KàvøX/ #).^ˆ‡É©pAΚ:pax°ê?ìé¼ S ¿C”,¨XRxÊ$¥ÆUBJ…è)ÜFƒ[!'4Iz³ :DÑ¥ àRTÍ::(|$:ÜÑÅÐFAž4Cb +^úð+dÕMÁŒ@6‰RÁ +Æ +¾H§x#W D,WµÔÀ8HÙ¤;€.÷ÍÙm7ñËÍÖž9æWvLKý6žPñq½Þùo­ä Š1+ é~…ÿ‡ì% =±ôßIsýKC§ŽZq`£®To2Nßx|óa=Ñã°ÆšÃU–øÿüŸï4¨[+ *pÀ¹ ì\ì÷Àquwi`¿·Xï·¤ÃqœÂÌke„µ ¬-Ôžw:õ“æ~-[¨Ùÿ¦jˆ.QóûÉüüÑxÆì˜‘U¦DMLëšð“fPØ2ãÆÄÌácfƒò·€Çþ¬™ƒcþâÜ¿åVœÅla;Ûö›¼â'Í?l뚊bôwÚ¤6 WhõjßL¬yP»U›ªÍ“½òV ç\ Ñò÷7¸‚X:HŒ¥§ƒæpçÆ÷u†=@BnñÒ=  ,à¤Ý:ùŸ—œZ±‘¡ðÈo+@ÿ¯ÉÒÕ~·WÛ9ªïwÿø)LÿmÂôŸt¾ÿ*‚þ†rKÜ9¢àIÜR»3¹s|.&¦2ˆ³!X[û³W7Ìb¹yÐí7k/šýA ®áqJØz¯ÝÙo ú ø=µ¼|¯}Úç„ýÓAskgs™Ázeå@¯ŽßJ 8êöÿíDè~½<ž)ÿÝ¢°_ËÕýÎí~4íß›ýa´ä^½ÕÿáÆþdΧ wýäÊÿ^®üÔz9Çï§ÐŽtx¤M‘€ðž­üNVÌn¿ÞN|2Y@¸fgʇ £‹I%ß9=YéöZÿ­Øku¶º­ŽåyÄz»ùâãz‚φۄÙlu¨“øƒã>0“Ýïž´þƒÈ‚àÇø‹­f¿Ñ¤ÑÝŸúÝa}Øü—YiÜ[ó mDÛ«q½˜ÔÙjó°ßl¢?t‡†c‡x=ÒôÁHÓ¡Ý ŽÂ;Ë<üI? âŸíçósüwcÁru1–ÿó:ì[ŠE1‹…u•N¡ˆl<™ý)òÁŸ‚ñ'Aü_Œÿ0¹˜~GÀO¡ ª£À#qq–lÔ$!”e/rIFcY|¯«¯Ÿ¬ð'+üî{†`fF‰°é®ð‰dVßþõ2©=2?Zꂲ8)~Y(¨ žxÌ@",Ú,(“gŒ«;æ@A/¯ïÚtå{ÊË¿* é)Ú±$A•vvK ÌŒ¹b}‡Î-辆b&PGG'˜j¶,TÁPRîeƒ2· -`z„5‡s„mÌ$®VCõ脺…Bz@2 × Óõ]¥º²Z¨ +Ã3)J3 +b. åá9¡\ÑÔìÛÛ‘(s-ˆ°…é˜ÿå¾ÍÄRXeaöWøÃLýÉ„;ŒiÐ…÷²Xp„ú+qV€,‹þÜÎTª<Ñ¥àøse(•:(Ë<‰vVú¤jÌ$!‘zÌõØ‹Ld¸ "Ãú®x “H%MÓî)›ÔWA4ì:³4lx«LKiŠÅâp#°/¨æc×®\RbØ»'%n¯£½Ô­Y'P·ÉÚDþa3~Cq³”ÙSŠ[lRJ^ÃAž‰¥«ð›¤ $…f†ÆÍ`ÚŒaWœØ«¨GÃAp™BCÝsbkÂnmfͲ‚Ï »2ŽöA)ò| sQ¶+»•JÄzóìpðp…]•æÔ#jÊÔô„RCfG6cš%"DŸ£mÈ0±Ë…m} ûðúŽ_.šÙPHÑ—†›#u FsÇ2 )â°+bx:“Ú³–È¿K(LÛP²x‘Èz^yæ Ä)L†K׆àvi0àÒ…Ê€¥Ã¡™ Á6éêdlÇm©Ì :-à’¢L4Q +’q ×S¢4ê2õsMuxZ̹© +Î2œæ@ǘÒÛR££„4œ­ð³Õ1w5¼*Ç'PÕZ—Ì]í Úk0 L·å2\¹ÔoxX•ΑS•ÔcnóŒ;žÃ Ç™-ÂÊ%t©"d–‚$¸R†pá¥ÐøC’™ýJkAârmqªñRÇ +檴]¶¥(-̺0]šAmZâÖd)Ó9ómEl–ˆ+ ™†v¢*KB:5[@ØÊÌÑÌð`›ãX–„Љ)µÒÙË-<°Ü3à!Þ”ía“¸Zƒü”F(dšpuoÀ0Ô 1Ê`:±†•ëÙa8Q ­ÖL+$.Z ıu$Ãös<+Š|E Ã!+eªuØÈ#¢MÍÒ5íP¢QYIRÒ(Œ†*rd%NÇp\µð< 6Šϰ>U ze‰[^Y†L1Õ +Š×|P– ™jõé"ÓV²§¶k% +RÅ2C8†ÑÕrlÊ0~ÜºÔ bË“*Åå^äiÇr ë*9—i‚øÌ¡¦&ÒK) +$5^¾ÓÑwO»¾!9uM iÐÆ¸Q#ó °@œ7ˆðŠû>žöëCgõþ¼^*Í}?ëõ}È»süåÜ>‚¦ü½5Ÿ( mç´gLkHªF³­½hvÀ‚;·ç³¿„&†qT\ß®-~øU^ó 5IÆ™ûýúôÈm~k˜±B†â¬%•ç¿™(qº"ѤýdJ3o(ð!Œ8QØmézM (| +J©(È´ÌŽcƒ(„甞ӥ Ó1Ýîd©D—µQôií†Ùe¤1 Ç•SV¹éÙ£Ýæ®[Ã%$}œ•ÈÛ@ŸÌIzÈ”8åFA@r‰ÅÈh¿™SÖM[+a œ·áÕA§W;UÄš):4*Â^µW®KR’"mVª!¨š–gÇ »óÃlr†œ¤4mjcá•d³æ–¢œ š“Ž3Ú¡Ó®EV´'FQ(ˆ*KŠza›ÂîSAû4Ú¡tJM¡H;Òf:Š~P)›×v[J(FBÎÜŸq4oû3âJâ.މ\ÙЦfÓÓ®“=ü¿c¶ÃÓå~ëðhèêßwµÜñ*XlY…3#Ñ ePÉü3»Gºh’’æk“+dD*šï9×£ŠÊ4 +£|`7Y‰ÛCXTé$}`þ9û%2ì PÕÑ0(SÒ7Œ* +•äaŽF -/³‡!ŠÐø£ë.z€”^äi‚ÇÞ,Vi2?„B…WX”Z&ÅÚMd}Œ(÷¥ÑÝ`Ž…1ó™“‚´"«H«ßEg3ÓãÖ²ó+Z÷á×Ô>Úl †¡£5Îç4öºh$ž+Ê.Êx¢¨ÖJpÁˆk'ñW +9‰„þDU ¡›ÿgÆêwÍÁÀL°14:@ÊS½hB`Kí~¿u¿n´Û§'­N}ØÜ¯‘¢0 q9­“ÚãzÿxP{7óGkxT+ç°æ»Y@Dko¯Û1?Üoö÷šýúlµ%~ö*ñ«ÝÆéI³3\­ëPãÓþŽå=#·<üþêñæ“î~sìoÕfþêÐôS4,¯q:vO~,'û~txsP‡[[yæˆ]”¿û¹ØŠ6ÿ˜©ü/œÒÁÁÿ`iüƒÁ”Éù. í£¶ÏZç­}ÌÔ}îîrÃË~…JÒy™—ùyË:j‚Õ}‘uÙ–?xa6€é¬íu‡Fæl6†Oû-cš\di£ßüàEŠü\züóBœæG¯dâ1æ3uÞj¾\d5_þrÞŽ±úÍeð#|Þ÷¯¶Ê’1 16¬÷›C£ €ß`°±z‘½ýæë³·Öî¯wû'õ³˜e¸âƒV»9±q´Ö°õ¿ÞD?—A÷úÝÃ~s0hý~!6jþ—=ÝÞ°¯Ê.äyÿØe%ç-«y²×ÜßXYÙêwT/²¸‘O~ø'ËH²¿tbØù…lØú‡/lòÞuºáàJ· O Ï_ZÜþóÜËëø`¸'_µÈ“Ìñ¹èDáùù´Þn /¤¹¦ÿ-é\qù_sFĚĞ s} ^ÿ§ÌipðÇžÂIsX߯ëwåßœÇå}¾¹ºÈy ßÃ8ÒÌJ^}¿Â¯O0‘j¤U zÝa¥•9Ï|fSÇ(ö{­y‚ÙÄmn»ï&µ´Q[:vkÛõÁ°Ùç'îA—KBÔìÄkÇnã¸{:¬ö»§½‰M[ƒn»>lÖöà W˜Ž—µ^€­“Ó6xÌ¡>NïÕÍ~5¾˜1[û¦µ¢ÚÕûýn½¿_kx.­¥’Å™mjÒÌÌîã¹Mñ ÄÅÚö­Š–iê³[Š`ç6 &pn[7‘At§mi/YWêßëƒÁþmå¹Ùÿ½YÛmþ9¬­í·†õ½–Aãõ—µ•v«WÛíÖ–xã)»ú»Èò<‡€";5èêÁîãÍÚr½q ¤…×ín'“xPlù|ЬmœÔ›µ¥AðY•4Îì¹¶)ªç|ü4•ÞsÇf\CÏ¡/‚†™ô²sꕆÛ9Ý;è¶÷Íñ·qì{¸ÆãG®|‡ÏÈàmg}X{Þiý9Ëa£—­Î~÷Á¹íS=©CÁ_[!U:Ùè4Ú§F¡zõxkF»›DÔØ÷}oÎØEÝ®?˜Áš_Î[ö­mülaªx9`¹À¹§ÏT9nž/Z£‘y÷`íÏ¡ó$“´<Ö<ÛÔ3‰3Zí·œð3æõ3Òx2ѹ ÒJ–ÛÍæþ2^|¿ð KÅy…kUg·}ÑjþaŽÝjk0¬wÜw!JQƒg”çNwˆ|Ýe<­ÆØzŒNàÏŸ™jBÀÏ>Nаrš”†w./èø…áÇí ì•EÊJ¿Û[ê7ë”çh„ži;n ¬•ÏòÞ.Íd.j¹#[µ}Únöà ; ³Õ½výËc./lX°íÌ¥³Q ÃÒ,7Ž,`ÆÅÒ6áB%µ9)²$|»ÙÞínÓÀD3ÝAˉ´s¹ø'¢âN´³ äËYDÛ°Õ®wš˜y¹dà{8ë+ÜÛ³?+2ƒqå5 û×ûí®Ùíífï´=¬·… WWEhUSy‰ñÕ²¶´1 ½±Â—& é/¦ïî6B:ÄþÐ;¾Â¸àHÓ§¬èï„vQrV«]g„Ç›Ðþ-ð[¯åÊ9‰š>­œÞó±$jk[;G4>OÔãÅEmÏÅTÜl<ª¨ÍÅpÅýU%‹¬N׳ÂZ«ƒL´«]M¦Nâõ¾ð©»7ß3lj^æE“iãÖÛíÉ­Ç­ÞžYâq|”«Íúƈïš0½þä–n»í™Ú(«¶·U_±"ûIè˜ÁK*@ôÃîÞFç [óvü9ˆ–cFkœÌ›¾š^HŽocE^ãäËü »T±rþöZÓ:´¯²Xb|aóÞáÉñüðÉîÁÁ<ųê}fóxÅYm>nyq秃¦aìÈ“_RNØc ‡&â?Ò×GÆ ÛóûÔ#î³ÅÓ9$Ÿq{­~‘ozû'æÏíÎ…'ÕÛ¿pçôdÉ}1n«{½>7›°¦ Îâ¯Ôc7Ö´  JžÕ* ¿ÅY­ðr¾môÅ‹µvY°C-û~ø"“Û†:chÍðíýÚÞ—ÚjßhTýÉ›½tBù3:P£‚µ³Å賺êŽ3¹G;«4åÐ +#&ó‰ýæ uØ!1–kîqù¤±ai9±]}@ŒêÂ|>ÚŽÑU·ûó'Î]yV cw™­BŒË„µ@K'x÷(±Šz9¶u¾Û‡¢kõQ¶ÚðÀ¨$GÝþœ6:¶U}“hG=œŸH|Üæ÷C­Ú +‹DؾÎm÷ûä5½vãËÙ\‰Ú4:ƒIDlÚ …øœ±>³Oízï|Æ…/h<ìVMdzÛ2æjŸÆ»i\ m0q§è 3œßoOfyÔ¦×?èv&ñ;h68ݳç1·G³Ððn\‹½¨È6z0ßiÖ½øŒFê}ʙ팸éLî«-x‘4✨´ÕeÒœ€%hÔ‚¨cæVñWÆ­òq|þÏÞ|änò¡••Výª*>™q-Ç(ýãÚ±½ýߎ.U'·l·&° Ón0둹~FÃn¯1«`ƒÁ„Çû§_ã«|>YÍ0fæà|­N; TBmØça)åÁ€ßÔ;¡;ÞÄÇVç™Ʀô¼cæùüÎ|íes¯¶ÒÅÄ=ïfv^>Ýz7[û]žcœi¨|±)½dÆtèSÑÞÙ·Õú³ÙÞjöš´ºÇ- +\P[«ëpu×Ùwq£c<Ìšº+­³Qeš*hjí׳÷ÝŽ¿Û¯÷zç4ÄÑñ–}ÙI½3FǦÎSt~SZSk’KÆ6]¯†fßᦔIa÷¨9hÖêýfmxÔ¬±õXذ—?ŽšÚ€‚›êd{B ßí×€ +jõ€©‰ÀnÏcXé;;ûÒ=­õ #¬u;5s\á/84uwEQZÑ@7jf0÷iǬµ6ìBf­…޲z­]ÿñäf0j œÎƒÓÆLo£³Š–ï†Fë95³ëøá[ƒÚiç +'ÌO>vçM×~«wŽòmÔöd9ïI…„âR‚Úlo71ÛÖEç°˜Êç·Þ¤Ú–[FEܘ¨"Ú–»ýÖI0ÛIH°aä5¬ɬÔ{QÞjN’º¿þ/íDw;ÝÆQ¿{Ò\5ÄA)Xª·“8]‹˜?›£ÁàÝÚêrµÑ.çC%8fÚ ÷¨Ÿç£– hŸ¸F‡÷wì$ÐÙ9íšµŒF®ŽC‚á('vcCïlfEû¶¼Þ¸ÀÚa£PÛ=:=ÙëÔ[6pð¼eA=agÌnR¬ÖÄ3B~G þ0’ælŒ¡¼XAµl€1ž\ÆZNx ÏhÝЫatûÇ^â£rØ‘¹ÜÉ—'õ‘qØ"7Ódÿí˜Âõ]p8:XPñ(ô œa=W9ÐËÀQ§ÆjÙáù÷' +cA—öº¿O^žùc£>ƒó^èÚõëuÝÊ©‚;h¼w âoÎ[ÆØ32Þ<ÏŠ.È2/výþ×(dcß°àÖAË^|Ý9º°ðޱõ,|#+å’j ª”¦.$£ÆïÓäìR£ßÝ«7ë_šýÁ_ÁS&/²r(ª«üªªùðä°ØÉÒg‹»IH§3\ôØT4!è¢Ê;.€qžòpé~1,Ÿscx‘ îI’ƒ÷_#TÅãÌÛÐTùë7ÆÀ5C§\qI¬¸C!‘¹Ã¦írËšµK;+…^mÂ$àêÞÓ+o¯ß~yçê­ú«Ó+Oç–û÷OŽnv.=\¿tcæêJ«>?ø5{þ`-»|sñùý»Õ½››ï®>^ìŸ6òõ5ù¸˜J]N’Áê§ÕÃɯ‹·>Ì_[¼}£7X<’ SÓ‹·6/õm£‡ÃåÃÏ6o«æÎJëÎÝÆêüüÕÑ¡6÷_›ñòÕõé›ù›ûÃÕOï—Õ›¹K'ÝÍÁÒÆÎðèúÝìòéúªúõåò§öÕ—SÓ«Éý±ýš—ù‹goß-í®Ì¿8{аÝÍ÷‹·×ß/ÞÌŸ\_½1}º>sÿ`j‘µþ›9þ«ï_æËíÅö«›ËGÕ£üˆÐñÛ•Õ†Øü¼xûÞÕ—Ô™ò`åÃᇮùéÊçÕýKËsŧ_—væ.wh¯êû§SÓ姙뵆~6³r¤>Þº½4^¹¾üäÆo×W®>__iž^»ûâáå£[Fý~j]_;Ø<¢‘E²PÏû­_»Ùúðp¹=}ïê\ÿú»Ó¥Í+Ÿaþ³‹·¥SÓÙ­ï—:«'×ï<¾µŸ¼»ÓÊó…ÁAºÔolˆëÇ7…ë±±úpð -¿ÚÌ_¦ÉþÍÖÊBÝì¯x|gfîFs¹oÐ +^oN/®lܾüríF©f_6Þf—ïæ+Ý×o¿Ø{Sî]~ÝÞíL›ÝÍ®]†-y›½ÌžuOw—g³9&Íû›‰xùñêBýö•õK×ßôa” þð{Á&SÓÉÞ/ +¾~wý6ÿtûåÚ#j¾rcí7êL¾–†t_%×ïÞ]»!WïÞá~^Þ¹}kÿÓ“¸“n¦¿§ËšG1–º ¼÷3w¶¡QS!L_Z^ýˆ¨6 +æ=•½É>5–vW?]_=Xxôy­^¿úër¶÷üÙí«ï.í5†K[¿6/íÊÔìþRþþõeóÍþ›µW¿Ý;u("ªÈôñï¬hÏ÷Ø {Ý]=ØYÛG|šnë³×ï^¾õ’vzžš^û(®¿XV¯®/öûGÏÕÍÇ/ïáºÕÏÌæ]»q}¹[~¨¢2^xˆw‹'ÚXèjjúÖõ;§3ë«m±œ<Ô7Í?÷“õs7Ûë.ÞÚþ²´ûpx:ŠÊÊNx·ÿª `»†}žo-Uñtº]6×g®ôfW޲í7k{Éík«Í~ÿFÒܺsËM„Ðá±yéãCÔv{î·u8©æW7>åu:û´¡ÅÎç“GKO?,?^_9xX$âÑÞþúÊþÉkdžcöàþr;»óÒ÷ 7ï¼Y~°{ùNeSÓfͧ«÷§›f¨g·Ã¤ÉÁÍ—ÝÑÙVÛ5ÌO7†÷{¿ì•åõ[êI#·6݃•Ö •·œ{»%g/o<ð«ºÕ¼yåÄœäíY ¯Ç×ï<|óÐzøÎð±ÔüuzóÚýáÇý“¥ß®.´î̬SWdK»»‡‹/v7êëkųWSÓ·¯'kï:zk7ºOäú•ìæ+³ç§åZãøó;vó•·W7 {¼sui»Ý»¶{V`ØßU•o]›_zôz§35°pû÷‹»ù•§+›ŸwE$2®]Y=Xºú!’Ûëëg/á2 Ïí4Í‘Ò{•¿òîÃß#I|}ÍÑûݵ»;‹Ï^šƒýê×ëwïd)þuiçÆbg¥Õz¶K»MvW=z0·~{MÏâ_a-‡×:Ô|÷ñâôrûa2{õ֟ϼ¸×º¦_4“\¿éì_ûm\KúÁû¥G/Ÿ=™gö|úøþài³Ïªßf¶lÄö»yg;ÌO¶&[ ]XÛ:Ëóçï›Vž vZ[o I®}^!};•¿¼l i +MM‡Æ§PXYد–ž®¯~zùq¥õ)[¸up2}hôÛkÂàäîoy¾½ß…ÉÍyýˆÕØö{ß•¡dîìɲȮ9ÀÝÕùÙ{4À³ôîoFQ{zuåèúë•…ÖÝ;7y¯byÂþéëé¥gOv^¬¯ÎîÛ?xbï^IòãÓ½­dóÑ^ÏÛÈUŸƒ|slöeåèÝ¥›×ïÞÿøÑRÖûy³ƒó–_7ªýÖ?³7ÁÓòaùXÞ¹äÿàÉÍý“vbˆT<l¿ñÞcñû[ RŒÇ¶G·7ÿìú½õÏv€Ý|ñ֣׿óñèRÜ÷Ó¥ûûŸÌ¾ÜéËÅç—JÜÜ;3§² $w€0|ìÞÑà7¹|f˜ªåCÝt±;XûØ{‹·ž_œdR·¹upºõii÷yýµàf;Y·˜šÙ<˜sܹêÀ˜š.Ûë݃³(F¸–»öô†]ðô¦¡GqòùMd¶teuO5wÎ=½ÁDàôJ^ŸÝjßZ_Õoäõ»¯ß_íñV~Ðífpz—7?!>;ÜÍž®ÎoïÏ-Þ|ò騉¨Ýì—õÎ +» ñÍõ>w[« ¯n-Z|^m.5?üøðäî¯ÞaúòŽ1/—OžÞ5R,R<ž¨å§§éƒêíÁÚõkÙA ±<Ý)e¿^þ\,Þ|ù¹uëàÁÞáâÍWëaWıÉv/÷¦¦Qbß¾ñ:{€}²›[&3ÆN6Ìþ½¹µÚì=ÝDu"»¼©.L®>Ú}ü‹>ÑÞÜ5‚îÞ¯k“ÎûÕƒÝÕƒ©éµÝǧKzqéíZc«=[Q—Ø3y8}ljùK>XxòbiwsŽa97:ùÛ3‹ý¹òtik{áýÍÖ‡âÀìøËkf_õ†ÄÑC1›×Œ‚òîùúÇ[G ÕAåÝÏ'f“/-~¾×hú?À^.{½ÃyñàÅ †™-6úØî¯ŸçÖgºålåObosCú.œ|…)?™[nŸ$†^Žßdwo>}½x«WŠÑ¥q;ØÓ2/žu¯Ù›ÜÜßßû<ÚäÍÜjR¾¹º¾ÒÌŽ—vWëb¹]\.yãskñæÓgmܰ€ÃŒPÞOÜi¼zkÍêã¥íÝÅÏ£´qy°Òºóx°xs}ºžÝË^Ý_y²òâžÓ3–/ùíVãíêFc{kY½”Ñÿpù’ɳõ™‡÷6ËïÖ‡¬ó&ÎB{”ÝzôëÒÁêáå÷*¿Ù›_1êPëšï +µ>èì Ù¢{{{ö×é@Ý·×öÞôbÍ›fVì^ùugýãå+;f}×ß­}ø4l rŸ÷‡k{Ë×f¦¦o>¾ž¾]Úݽr)"–{®ÛMöR1Yl¶¿¾;ƒ@\^_YzoTÄÅW†­ÞØÕÎgH³-—Öv—òrû°T¿-Ÿ˜E.'g6APSiv®scשgwRc%Ý;^¼}·÷ÒÈÊv'¹2¦‹æòñÕáÃeõú—çî¼SW/´RVó¢^fæßÁ(ÇOŒù±Ö Ï]¶Øiø|f¹:½lL„7¥ïâ¦(.=YŸ}½5\zôZìƒÞyôduÿ¤¼ÞY˜™Í.ÿôøÐó_bÂÝߎtpRÝí1ÜëOºŸVʇíÕ½k­éró·þíõ¥vçt‡VèÅì>\åÝ|²²ðnõÑ£Û ¤ªÉg;sëkâ`fýæÒö/vC_Îο»ÝY_º»œM÷ôêF½==ÂÚ[³7﷗ί>ÚøeÅpËøÝ¾qºõz}1~4{ÞÙ[¿tí†0&ìsø¦”æä¤¿™cx¯ºM¯ÍÌ’q™ïæìÝÕât|ûÆH¸µ>³q²T½{ry}uëñÎútOæò²y¸˜.¿Qþ,²d~ò +Þá-å;—W–Ì,þÿÚ¾s=y]iû8‡˜Þq¡zoB@BBè°ö·×÷Ø?I6nØÆ”½žkåÙŒ¤Ñh4Í­yu8-’µÀ—ŒYè,ÒÔåÓ-ãns¢™6¦¨H1³ðƒý˜¸Ž®l-õR‚´|5$I¦Â n™‹ñÍ¢båf*ûóŽOQðYç{À±"S“z¶Ÿ5d~ /Ëïåc)3£Ó#SQB;Ù+§œ•Å+Oj#^û&cµØ½À rÀV"ö‡CóÀg‹9‚óšüžò]Q2²k¹ ü…Œñ—ííì+c.füAF²Zëëàƒ¿x}ºý¢w‹¤WûXiý¿•_ýÀ²•Xþy3ã²! oT‚¯ï€cåYI'=Üg›Âظ>ÓÓMÎq彆±=HOÆymbe3ò賌ñ¬è[ŒôïÜ^DŒ7ï.z +”¯ÄœuLîüÛyEFêówoêdŒ§í<á>%ÀNì´y{rôÊÊìÔ™þKüþVc©ü¬vLÌæ <ÍÓçFñ¿É +™Fé£1k.œ€5~i¼–¤,XÆŒÝëfPîìñšuVÈÏÁWÇ…ÓÏ÷²¯¢ùÀô(ŸàÛpzÊŒ‡ä +ÊŦðE)ú.opZ1ªý5üml®r¹Ìè8pdb¦yCxçE…Ö0çA,Í1ÇÂê³g³þF?=mÄÛ©oñG¤½XÅuÖYì*Më)fHÒh,4t™\ô^w™x5¶ –§Ð5èõîˆÀ{ê39Y¦¬?®Oß+•ž§?¾òiÖ=‰^©ƒ_ÏÀµi÷;œZè É"µ…8Výð5Æ9W&uŠ£cɰ8LŽTf/ƒõ³aI,C¯Æ@Qü +®~j̸À Z2DkÚ„Ç’q=6 ¦¾yÚ’yÞÐ1\fx׌¿oJcodgYò·ÌÇ Ók)m$À~ßK®8ç,bX{û?€c‘µšvæï`¶ErÙîh;F:’>2œg‡ñ†wdtÞ}-¦O¨èâ.štöŽ’5óÊÓ«·Y¹ÀLmÚ3 ö͵w{ª€}áüÐ/o ok÷GKBÆPòE´Ù—ŒeŒßëÔ×f`C®#Iÿ5£ê~èndOÎí0^ü°ø¹Ñ‡!¦ôçI;ôWrT#@Ù ¡ÌÈÞ +ŠúÂÒi¤7¢e[Hgœü^dLðÔÛ/h2K`ëÍÆ7»ƒ FwTRƒŸ®ŽZÍ)€`aÒ*sýl£kÀþ-gLYC&·b·E`ƒÔÖ;S›Îïùï¨ONí3EÐ&£LéJk„?‚öÚ«ÀÓ=ðÅBCÇ)ÞHúF`×9;l—cßÄç®q4ÊÅBƒf·Î7ˆÔà{@‚ý~ý/æ:ú¢:óïçtX`Ц3ÆliË…#91c åõ~¾½ G÷ƒLcŽ„k±žMôïö´5/TJɬgóÅfýÜ¥p½c–w–´`O°Òs¿9ÍBÏ© þ/ÂBÂHx¯ÊK!c/)”dƒ‰ç£á`×/®Ïwø|ÞQBB\䥙ÃÑÑyA½¡__Êħp”£&E—Pm'ë3öõ +,M*ˆóg½ü;ŸÜí¸g˜\~½|Éí¥ðq Ylþ“ûáÁ}ÙË‚'ÿÌ˧¿ãÏöoÞl£hˆaXú¨#¬‰P)W%e&†}8Qÿ*ëJTè Ãöm3ºsï`·;~2åþ¿þJ÷´@Òóï¿ÿb˜eœÂ0«I‹aæ‚Vcð{JéʿܠŒŒíky|ÐïáW°µ|ÿ†ø£õg±yµÇ¸€Ï=±Ö`gL&ô5=þÌà×úš ü¡(üZ¡_n||á×Oô5î¯Q[ðÁ¬…´_ãþêïød ï`ÑÊšœq;øl…/iߤ¾Qà“ý þ: ì­† ~E õ­é8€=öä~¿6áWGzٙᇠøð$ÈÅt¾¢¾@˼ž÷˜,ƒð¿`ýÚ.À +Œk3¯`=sR¥¨•J¸Õxcw0dÒ + xm¤§ú`íjSÅ5D,C̤ êÌ·ÅuØ‚Lå©2™Ò÷‚ø¸E¼ÿû¯q«ßÇ.¦ñ*b;‡Æÿ¢!†ƒ×übϺü  yOõ{ÀòÙ6B…à× ¸ºi*Añòçü®6G§2Oòï\k}HZµzÔOõßœD6Ñýx¿Ï¢ÆDÚ¥sÃö˜ß»¡-Y†ÓÆMÇšMô½ãÄ28³ÇvÝŸO”8ª g.¯û3ãú¯¾O™×L¾âõ?aTi.hK—KôÊùléRæÍKéOŸÿþëZŠ`¡>î}gEW2±@ß³£Æà[õ#N¸õòk%“@&®«øesûV=¢)jM9”?ä*`²Ÿ€ŽÕ}‘üµ%Z†“š ëìïÃTÊÀé¡­@Í¥ 0SÀš˜H“_Ù8±wÀ¨ÒéÙêS©D¹)=–ÿ"þÓY¦s}®0í,÷‹a©¶Èì>‰aѶSËŒ•Å:Ðb–·Î³V$ãh\ÁÌŒ5à7°bnüø¿Þ¶ãÏŒÒo?|䀲1­qÄtöÔ¦'mSÌàS×®x€ì›‚x3Gÿz˜%]ß`Öbȉـ¥…Ù[Ãæè§1çÔaÁ\ß?a _UkqðÍ1JwÔcÔ©éÅ<Æ×æµë†˜í1¬LaŒ;‡›Ø }~‚ÂÂÆ¶‹D +,Ú +c±5aÃAk +Köt#,mÜë±LuÃr†mËW¶:¬VU¬41Œ°·¨Í‚UÞ6nxìØ´õ^Çf­ûšEJØb39bK#žÃVÁîÛTœYl÷ÙÞaG;™ÓbùÉI«Û&ÊZcBgÔš¦Ö–ŒâZÇÁ0ÖâåIHK啯 õü Zÿ›É¬ ×}mÄ4yÕÆöÝ6¹x¯k3â[›äÿ´¥~®¢­ÌÊníû_m­m[ mtúñ?­vTÇFÚé +Ôüʓڟ& °ÒmÚmÕŸµMM¯N[ßëuFwt¡³üLÛ:GÝ›ÓTׯó)›Î¿št¯ãЗ.öþû¡K½*º\ÏèJíeXWí×ܺÆoØ¡ëê,&Ý °Õê&ÕÉ^7ÿ®¯t¿dñWcЭߓ ÝÁÿÖk+Ñ/½ÉžüÖÛ†Ù…õ¬¹Òú£>RÜbúdŠ0ésTÜ¡/ÛÚý»ýÖ·Á¬¾ïjUõ“ ®§ÿ*úåìÿ·Ç¬Ó€…Na`;o%ƒídöòÛdmðã6Ãë›1bHà_uCvQ[ÊŰÅP÷9c†®öØ1 ÿ–;Ãì÷Çkø«†í×çʈÍ&n£i9«ÆÕÖèöiCÆ`•èc?q³Æ`Ìz[Ec¹³\F{ØøQËNüÇmüž{zÆuªí4ž–¶Éxh;L޹«cr·NS¨ê›ÅÛ”¯Ôg¦j?5µÌ[Óð´(›¾¼]›iUÊLÇe, +ôŸ)ÆÌί@Çì xƒæð¯ÿhNgBshEsc]7šûýɧyVØ–Ì Ük>&ŠZ‹)1ÿ´¸’¶ªÅW*E,ÑáÁiÉîRKÕ¹œY:…dÛ2Þ`EËO¤j±ìþü«!µ³YÆžÎê¤vÖhν´æ(ýÜZ3n&Öîf>´Nÿ&}ëògг7£žÍbùØHÿfd å´S[jŒÙÞì©?[»ÜÙÛ&ÚƒÁö[ö;mGí»Oc°›Gº„Ìäß쯎MÏž>d~ì•σÎÞT)ûç˜JÛWÓeÛ¡]7–‡!bsø‚ޏ#þ¶k;Š_GËÓ§ã~»ìX:ߎÓ÷î´%ze§×8ýsÆ[P‹³Ø2·­Ò«Þ9)6sοÂúÏ¥-P¯.ÇûûÔåŸé<®ä)7tU‚GÊõÑ, ]@=®]u8ÅÍæø+N5uK<ê™dð±ªÃ[ß©6>­Q| ê% y3تÄ›ÅE„ë–‘Ÿàe¢¹ñ‘Ä”Hnˆu®Ú" »Ÿ8I†M62²Iÿ‘Åä°Kv¬Î,9›×}䮤3Q–T}MyÝ–1•ôŒ›TÕ—(Pƒ€>Fý–¾ýnm»‚k n×1is‡_}Fw¡kÓº;VýÑ=ïêî¥?xlKëÑhû´žl2ið4]‹çÓñ{vv«Ïkµ&¢^?1Îy3 WÝÛx¯¼Ó?óŸwè}Ö¾Ûë Xf°že‡Åޝ!—¾Ù~cõfpm)WÚþ×\në/&nÿG$ôæÿ)Æ~ºJŒ ób50¶¶ZzñÏõ`¾û_íAëO· f´ÐYÑl°;_€mD#œÒBúâß&äNf3¡TÊt5RƒRhÖ.˜BÇ Þ~ÅÍ:Ïk,ùûóZ]|æ_'þ¾åu÷õ1;¢Ýd8bYÂo“ÅgxÔÒÃÛ‚‡ŠØ³Å}$œš"oEk>2ú(ƒÑl¶Æ¨Ã‘\F#oûA´²-U£“Œ=Ýo'˜«’uÅâ>Ê«› Xl¶ZnãØp°ŒS“ÞO<=ë~ÇÛßí¯ø¯i²{öåo"P;­Å-¾O Y]b»ÿ´-¡óÍJ%ãd)’¬…ä×4ÛJé;§YÊWy;¤ +§35h/â©í¸\O»Œ‘ŸtÂoµ¤›},žþ±®ºSû÷ ¹ÌÛ|ÙÌL+ÇC ZÂYÃ?Ìæ-o –ìÀðYÎîl–}“¹Tu¿ÌuéHneýûÎÛÅH>n±ü曽Ïdþ7Ý,'ò­™ël…zc1(,ZóHÑ\éŠáa«ø>Ÿ€¾ü9–Ìþ}·‘ ¡T7Å­¥E«÷[¶X«ùI$ËæYþM„°7›ï{ñ÷¦{omîímõÚOUœåL¨’âd¥§=Ù+»ôÒT%]5ퟪ£ãðXÃ_§š?³ÑÖ*³Ac¨}Ù¼–w³«Š¿G©_ß{Ë¯Þš…ºknlÖ³®÷i}X±l˜¶okøÑ×F5h®4¾_Ó¦õ³¥k&zÅ`ó£«5÷в冉Vy)·¾Œéß¶%Qwk íø÷W³ýá7hÛû¯HºãÍ ~;›9Ôù^–?»¶±Þ×M šÓî Gú?°ÉÏ×GpQŠ~4ìÁÍÇ*m)õˆ¯ƒµW¤¾‡½Ùpé[ŸX?iøùè÷§ÛÈ8à ôœšµzi°iüù†î‰W7¬`_ßµ9r6›éQÞLøFŸ…mlqçOãäšXއ½ãçDŸŸö'ÑX«=ùˆUë“S¾Z›†Þ«ÕikÖªN÷Öéû§ÿíØÒ>ë¢÷¹)æ'3¯ýûwVûÄ÷³U«g™» ¸g^ $æÉÐû•Û}~UÚÓ×ò+F}S$•ÿ®Ô£ïåaƒ-¨Ú:´¨ºV­Åßr¿ÿq÷-¡ŸZ3ØûY¿•€õùë­~æë}Ûêwû/ƿٲ•Šû–‡ßíäï5]óÿuOÄ|¥í¬"«Øk}µ’™ÂÚd˜ÖiÑ_ºððÆîs7…ÕÞ,¦‘×-‰WtÛj}4ÞnlXAcØùÇÏ®Ÿh÷åœïcÎAk?²ú²‹á+ ppw¾Ðx=ž7€"ÜnþVÿâÕK¤eir8žw½çí‚[«é[‰³ûÉ ÞÑ÷2YÏ<µÒÅÕôJ~ˆ£¡Ì…ÀIAMô¾·VEÿêz]·Þ’ºôN„4†x>0J¯gçßCÞÃB‚%æß?kXóù™A9ù%’Ž[Ä3öÙ¢­© wÙÊ[tq¤à'ÒýZ Rìƒû =QÑÆ1‘ú +d—9Ý{x’ú»ö)i ¿{˜…Ê…1‡ËôLq[dù +¶-̾øÆ_`[q +Ö1{¹“Âx™Ä]á®UïÁ’–šû@Ê q©¥;ZG¨„Ÿòƒí÷ꡈP¨,÷ÏæIaÖ›iܾ}+ÄŠCÄŸ{m;3›w+½ïà©L·‘ Çß„5î[3µPúš-é°¾ƒúJ^¹îÒÛý€žg‰_*öûС*±çq—»NwƒkÙÁŸ9¶Èál6fFÕ\áÈîøáÐöŸl‘,fDGã’Z:]Öíß…~Á×ìøu7%¬´¿”û5éJ³¾¡'˜:%+ê߀™$ª–«ÔûS̤+}ÅÌûaØKWZ%ún-´r•3‰­ö`²—2•z扩›–®ÔméÛ^Éoéž‚MX\tÍí_Iª¯x&QŒÉTêÕé×{KX¦ÒîÏ|½Õ¹J—­6‹½‰Â¨!Yi6G6dÙK~DcT)ÅiZ8¦m ÉýS¤«µ\Žª¹Kõþ ¨Ô½¹¥ž`*­šL¢J=žÕhËUÊI2]íh?X¬2•Æ&^_FOHV:ŒŽßå*Íi zÊêK÷õt‹ù»t¥µ¤%²Ó¯JR•ÚBÁW)¡(Y£±Št¥înÏð7ÉJµ™oŸþ}EV¤*ÕðÌ`‘é«WgX®ËI¹J'xÖ>nIWšÅ㦹Ù×E•j buö(Si×a18úæ3ìM÷—A¥¯xÉç `¥VQ¥ÃA››o¼ï ªõmÅò[ê}Ld*õê|ËYf(Wi +/[T):ýö5¿ Æ~÷oï’•ÖC&J¶Òâ¼NáR•BÍïî9ðúÈ¢•êëA[ÌÍßz³d¥-Óú[¶Òú¢6ž¢JÁ¦ò¢¯½,Þ*n_¥+-Q†f&ö–®t[ÐJU +t2¬¶5Êj2 îUðv´˜’®´I†µÁ@²ÒAe™G•Âõ岯¿]Ï,#SißéJß~·«JÀO‰*µ jGyÇZ–Á{C݆ÉTÚmâéŸUA²Rÿ›C‹Å Ç@µÁxÒœF¾S锲ˆ&å£4±¢JISÄœö´„­Á8¬ÔÎU +jÕ²¿»³ÒïÅ•6Æ0Sé1jõëOzºÒD—È ¡}hF0P ¨Öy©•òÔWPiòx¡ +sZ/]i”(:DŠÐ¾u¿Ñ+ ¥&‹¨RX S­~¿ŸL×°R\Té~ŸoÎò[ÀD•<¿Af¥‰kN{µ›ù¸¡aì‡ùdä6*×47A٧ݱjÉ=]๱áÄ=½Ðü@õ¦Œ2¿c`´%ÏíúûDO½~bÔ`ž–þ‹Yé]/´©ç´R¬æƒ}Ù§~Òú>–º˜ M,Ç.ŸÇIãǧìÓ’m%åŸN+_!c^]Eû9ÍÉüÚŸ3æ^›úé—iý¶iû9§_„6xÁ±æ´P_K=§µ\ʶÜË>m¦.Lþi? Ÿ9&ñ|lúô²OÕmNöé²E&jÜÓ Ž­–™ÈPî× IµGöitG:ò3|®§õ’ܯ˜1ß·Ê>MÇËÓ¹ìÓÕò‹c¤Þ”yêÉáé°õÜç 9$zjkÔQæiÒù*ž•¹Æ8ksÏÝ·ý]¸Kâ3S/É蟱á>Ý2ÛÑÌÈC«žÄæðFè1ò¨‡;Ì$æ(º`‡ùÛ€œ°,ƒÙSïIø§öoìîÖL}“÷ÄYóíµ¤)\u0úìsöXDG™À +47àN‡7#\eÿÚö±P­Z#¨ïë•­Oçú O-@;iÓûÓØé¨Û½VcàªE;™J½:¸ÏéIWêî~ÈV +‘_BdñûŠv:²•Â%ïS®Ò¿Rwì‘yÕúßu^¥3£QÇUЬ¶RJÄ^hý³=Íþ *µtÑî•_­€ÁaR¶RdýËT +öƒÀúr•‚¾ú:­0øà–¯Zÿ²•j Ðþ_H÷õs*UZ2ÉVŠl +®R8÷ÕB›¢!Õyà\=úÄ „%ù1[©yoxZ­ùs_æM¯n7Lw*Wßó,¹c´Eô¹g´åÅÔ›W;ï<M$sÚ3ÊÅX‰f¼ëG´s"[ó¬ÁlÖ¡N¢÷û‘­åuËR4#‘@Nÿ‹Z d{) ¸&iX3Å©&¦úHÚÀü±—7LÈ>WÀÚ– = sá-ý’ÈûÔ^µ˜§ ìŸw¾ÅÌøÌ*ìË)XK–ßÝq!Êø”@“›UP`„íÉzæm·3ê˜×ƒªQÈ@ÖãŒ<ú²-Ü%I5jÈ‹ÅoÒèd¢[¶“¦(Îó£‰Üˆå@[N‰â5¦Ã?LãéͼDÿL˜lÿ4®‡èìžÇ¯®½>~:¶VFƤzצ³ÔßÉ'½³PÉ,b„5ñ›‘%¥Q#îgf…7I'W‚™–¬lw;ç%ùŒ›F’æ<™ø”ù®‘g–PõX.UÏ0-T=”¬êÑ\Ýt?¿ç3m²€FZõHón˜†6 Ã`™öØÓvúÃ;b-Í»®“UÛr³ùã$»ÖÕÞÞ5þ*†:GE[ò5Vg‹Fæ4A²!)›¨WüUŒ×«yÕidFÿB¦A-­ÍM’Ò0@vÀv®Ãã-; ùr>¶Aã:)™a²o‰‰Þ”Cm ýüw2—_¥[ø,9L‘ƒòOÔF’/›rE ¨jˆÈ¶¼'W¦=¯!ôÙ&³D}ç ëºwÞœ>”±±=äà0uòÚàSÊ|ú† +dœÀÄlIõ!3AòÊf‡ÆpK£tw*¡¶„Snp4(/Ëj@žSj÷ûòý3©`¹FÓ¶Âu†Ø’ç|}¿yx¨×~†P¥ŽDzpÈršA '¹ñ‘Ù“Ù_Pjå“9±Rb–ú).»íA»$À¬§¸€YìG¿ ô¥K8Á °/Â).¹ë¾î]R«Uç!Qò%Ä.Yqk”\²"ɪ ´àe6Å×]² k¼‰ÄŒþÍn’ŒK(«uo°»$qS +'á²|‡{ÈÁŽDB‘*£¥~¬DkªŒßGcPòÒ­ +ðp·û߲庯O¤ +dü5;^U’ÌÓ›OÃV`JÇNbSȼ3‘ÑÉ*ŒiÈ墨”¾…w´=†ÚcPnZÿmúL"‰àíÅnZ‹"Kø¾ù¬Y”»v]΋ÜâÇ®/wx£·Eñº'×!AAÒì½{@´iðh®Œ¹:ÆŒ®8é5¢¥NΖÜ-t×Ö!¾-K÷…·ÔÁÃ*?~ö +”©ÙYÇ“ä$hó6Ÿ÷eŸ;u©ÕNx*ªú“ó·Jy[é…œ¿»aòIï—À¤Ñ>¤@£¦¼äiTÓn$ok s&NÓytÒTØÝ$G嬓o¡sûºÇî÷%ˆ No[D…çƒ&d]ØÍB‹3‰ÂTŸrÂDÁ§Ãõi¨b¹ÄHçÍg|2FŒå´ªb%Ïü X£–– vXŠðTh4II0&¶{T£59vÞ½ÞbÁ‹‰]×h•'HØý•ÙÖæ  Œš”F»yî:·k´ ßMçq©<~öŠè(œÙföÇ¥1HY‚E¨µQÚAó¥m·ý]o ö<¾qXöèìy}ù2íäÕJË, æyå(5™iümjka7)YAVÍÞý œÌ-´—ìÄï1PÀ¨‰‚šä4Ìu:êL{Y*Èè<¨Èl¨E'ï×éÝUº—%N±gøªéµôÏ­ ájJØ÷Xš˜Ìdï*ßÒ¡9ûïU5J¥D\L.fE¦§.·žE<åµä΂„–;|cŽum¯tLcŽ85„¸¹´‚޾¹åq »DЉCwcè”tH'?C'[)BÐÉ¢oÄÐ)#èøhÁG0tÊ:Õ÷†NA'@ >€¡SFÐ) oÂÐ)#èZð :å÷lõú‹‰+@б;‹1tÊ:d]ÇÐ ’fUSFÊÚ–—G‰‚]T4IÒÓ›º¸mU‡—ʈöÈwæÄÖ¯„s@­§·—®ö· ïŒ/%ظ›O!«@\…XQv7«ƒÍç­kNáŸ1å8,uýC¾¾kÈ9Õýy®.ç‹z¦»no’ òñŠçJ©IR9Ø—›@sªtMZ +ÂÅöÜ :Þ +BÇIƒÜî6–s£›ÁöWu:å®iT‚Ý„‘·:‘$ƒ1ÔcLƒÝäŽm„»¤k`7ùý©òO[¦ƒA[ÓkÛ´Í @ +«#& Á".Ol¦äîòQΚdnÚô¢Y)·íRò!”7ALö­¬ux}o˜%u–ÍÚc—®³kŽÃ¥+r“€ß6%ƒfï8±ÊÊš]²(0ž¥$Æ]5»TãøN×bàoÀñM¯á_t§•<4M£lJ_ÆÀ›Â \£bRMùñ»¯:Š`–z0%ÇO-ŽÏ¿¿†‰Qat:$ö4„èž;ùC¦ÜBìºÄ«ç˜ÐÁú Ç®ÂDÕw’ÓhwqLèø%®Cè”ÖK ¹ÔÙ²>ßËm;Õߥý–Êx9 K­pE– 1&‡ü3VœÝ9›=vÇwe³÷S½Ù“# ŽQ¼ƒÄµ«QÀ8³·j¨ƒÊÝ5B#üúúr6i¤§„¸]w2h]Ò•&³‰»{%Œœæ +ÌYÅ‘'êò•'š‹í•‚<\„ò›SG,çŒÈIòoþ6÷ŽÄV‰¶”®ä.´Ž<"ê(¹šßaåÕÎxn¾ËÚc¿ùÛÜ;ò0;qÑÝ|Z\ñ4hD[ y¸Ñ##h’ EÞâþPh’p2__ÅøäVÛ$åèôë 8¥&‰ïîpŠü¿4$é™òÈ<¥,a½ + sÆwž£:xdxûýÂã@À¬Ýq íÌZðq „¡‰<2rˆÔkø<÷MI?An\±LE›6 +aPÆ$n‹Ï‰d€ã¬™žãÔ] š¯Äôª¡ÝÀÎ__ €LÞ»t|ì"tA-x WwsÐìe„*ÂÕ©Œ×SÄÕñ £ +HáëNТâ%U¼Ù˳-Cõª—w‘Â2• Ýó.˜ô<¬å1uÊx¸Ûï»']]=÷Îâ<œR„êóðpÐkýà T‡“¸TÄu?N uþéÙx8ñ½£4"îÙx¸«·<'8±RjyN¼“;ÖH¶Ç‘õp{ZL$ %Œ‰”³-ÕÄD¶6ªb"¯ÍýÃ’zÔ H¢‰ÇÑ舎ýÚ諤£G"K…¶Ç' ¹."bà¯k4®“wˆ]Æ;órÙÈD<›vÖ‹ˆgÓîÊ@ˆ&¡¬·§Ózdrà#žWáÑiˆ)^+#¥Çd§aw«v*Xãß·í%í9·#:·M<2 ó dÊ¥n»JGþJ`™Û´ä¬/¯¾zšÐ+-º­Ñb¿ôaAð™òÅNW7Ô,"•ÐÞ Âë³ÜÅÂw!R'Ú‘ +©JDêD;Uã2¸õ{ +"µ¿{"Òy"âÅG¤B*Ï@¤B:ê®m‰¥âúБ¿4õæ #‹ƒ}á4ì<< EP8i=öl(ŠçWŒèyNr\ž…»ßo)ä˜òÞý†}åP8þD ÷?ÂIxþP8iÿ˜ÊýYWÉ0ä«þýÉJÀ§…l¬ªšá…öXÒye[¤6Ð ’ò¨ò(ªp Cbò7ÛÝhÃ\\2|ëáÞUy„£t;/PåRKWËup³W×—½G¼8œ½£Ë7aÖ8»T}Ì —‘Ê"ûךŒRºÙ) ècÃL#RMÇ\GÐü™FÔ×EiÃSé},žó6 +É„ó3™L¸Š0 A}{^Ž Â&3'!K +uwI F©';óׂU¾x Án¡ÏJ™ï|æUêYX ¯ØFaçîv”Àn3—l¥x¦‘PBØ*?å‰\¥c…J³Ž¯R1+h;ð¼pb°›»³(±™ E0­Y ìF8E• +óñ…Vr;¯N·óžúr`·žêl¥Œ°Û4²•KóÅL®Ò¹r>¾ZG¾Òô[/+Ë^ýš +ä*­ vhTÁ„ez>1rTù^Hê=Ú« xÓÝ/©¢è¶Té÷˜¥³ä•0Dßλ¤Hæô'^P•|Ç*Bn…¬mM÷EpFT5nží¹¡*öšÈç±Ú©hï\L¡QׂS¯Åyл×gf’“J;"q§Š +ï’R&¹›¼p½”êÉ+hHt'ä q}×’È)Æõ©—§+Iädû'•÷íZ²µý»žk@5Ó¯åÝ¥ö@þ8õó%;—OD$îª6²§÷4Ý}~˜[ÑtRû€s.Îç¡éTÞó šNÊ'(ž/£é¤°t÷"åÑtR¾xéHûGÐt¶0sVòþ±‡ÐtR¤®ÜršîÎùF4Ô9 »V> M'…¥ãï÷Ÿƒ¦“ÂÒ©Œí¹M'åk?g`šNjt‘§÷©h:)ã†;ú4–Næ¶ùÐt—MZèä-¥{ÑtRÆ©Æðl4ÔøIDC=ˆ¦“ºšSø.4œmù\4zŽ=‚¦‘Ÿ‰? MwÇnFÓ)b¬ž†¦“ÆV?M'EÔòd4Ôi‰(þ h:)õ ܽ>MwådäIhºëëË3ÐtRÌà¬ñg¡é®!¹žƒ¦“ÂÒÉæã{|èà6€‚üb7]Ý$ŸÅë2I¥87‡JàÓîÊd0ß½‘Ëes¾º‹&á)ϳóÕÉ[êøt´™nâÇ%A$$Äd^5,TŠ€  ƒz–k”¨IjUŠìrƒ©»š9uSÚe¥&IRÈj>)¤]–Q™pDá ÚQúÀöJbseÏ›-K)ÑÝÃiîx÷\©4ÉïIs'›]®¨ +«¤2Í’KNU€„r|2—èî±±Êv·j²Ì(z©T¥¹»êQ„Œy8ÍcÃ('º{8Í}»’èNÝáѶø„{®¨h“PDõ8‹âÓB”¶EÎä¾Ëº¶¨•OÙS˜ îjìá5ù„0:¸yVôÀ«Ò©‰hÖ\GÊq¨Æ‚ZÂo"ƒÜ‘uý %Y]†-P³Î$ÆÁKSeû,u7”ÜyO¶ººØ%ˆ†Bu%\u4 u5~Lu4 ¦.¢[9°é¾§ ? +®gF_%U¹]¥¨ð"»êϘˆÊ’])|ËŽˆ©ÖÊå€këëK`m}ý¼[!±§$2F2Z«F™ñ×.YV6¤Xy5ß«R µõòH"ñ.#¨wâr1ÔóÃò)ÈöæãÛ-‰KR¥Ó³2‚Uù#bÕs¿yS¢j¹Ó7˜xías‚¦¢Õy'Ü@Óy4[5Må< ¥n8¼-Vµ©ÈpÓ ¯Å&1 [*€ ª<ðg¸;ã+årÜÝ1 %‚+îÍ[}[†;%äãÓð,hL†»§dÊ»Š'R—)ïQ<›)ïñi¨áNˆKRƒ¹'ÃR¾W˜ãîö wjo5‡è§ÇµýgæÈí^Uk±ëfŽF¡C离X+F>zõA|aY}Û=WˆÎzóâŽHç)xÎ2®n/v•Ž<VbÒ\»f¥Ë»ß.b⟊Ba¿˜†Aó•Pá×:ç}S cRb2…‡â(oScvòŠï”#ÅŽ‹,Œ)hV…PWܶ³³2hV3+Õ€˜LáµØø¾w_Ù¹ Ä$As'*¬´·†ÃûÀ­ü"ÃPâ²ÄN—Îñ ŒkÒ)«ܿܚ‘î¦tˆ•òöX÷yWSuÑéÛ“0®]Ù«©n·a¦‡›Ò=^É”çºãÊ›Ÿl† +ÔóuŒ+h’jԳƕñÁ(ù¤ë;›~ñ– 7RK"™pÚ)ݼP×RQ[½ÞŒm^ð)[Eè¾L§Ÿ™‘¦ˆ6E/<ȵËó3Ÿ ¼·è;¿RNc8èZÝ*ßU%ÌÃLöº2x8‹<o ¡NÁðp«öÏ«ÓûÞ-9^_¶RÐmfKÉöÏê>š²•šòSç·\6 W)‹äâ\õ¼J…дƒÉgäòR"”£ÅíýIUª1@‹sÎ `x1öÏÞâkU¦R¯Îà~K9¬7R¨4«÷ÊWš­é>¤*Eyßü9´R\é»RÁbK¾Òtº™Dvjõð¹ýÄ€0OÖ°K8ú2ïQI\ö=>¾[ƒqmÁÍ1Í-“ Ï]·ØèdkopñL*ø‰Ù…NeØ$`ªÇ‚NƒYÌ®NªX›í°ØtÕC"Iº ­’m”dùF%Õ@›®›ÏÊÌ‚ºW2³¨õ$¥”C«d‡î"3 ¨ ~KšêNtó䨴+š4—4êäItèukÿX¯5ÄÝÝœeQ¦IQZâù¢šé7Eii J’÷ßÖ$ -åã´˜ö\ÄÆŠÔUº± +¯Ó—9SîÛJÚyW__ñÁÓϺ¼±ëÀÔÝp¨¤è^V{Ê3L?r-‡I¼¸2î.°›ô‘õM÷ZÓwz–…·hBࣗÐJÝ'‹»¶k¹¼+Na$íH±N27å;×0™§í‘'±†¹÷Ô›ÜÉÍctbu=} eb?ÿu—ÊÇ'ëUqï.–þýíöˆLî'S¸#8xì"ŸÅiÙ”‘L7a¬7ÝsÀk’ÿ2Ë*ùޝZã‚&ñBõ™ÓjÞ¬½ +¸Ô«€ròï¹R€^Ki|eü¸“÷Yö:PGµ0ˆòKf™¹Øµ,:&1ºV˜hUyŒcW±<ê;)<¹|cWóéÜı’»/Cì.,e2»¨¨ú9€˜*  Btº + Z à¥?ù Z ÿ†ÃÛQ€j1€Èk}7 +P * +;Lqìm(@µ@ȱûQ€?•õ†cu+ +P-Ý#ß…”iÒ^I·ç²W'åSŸ‘푤|¼¾ü“ò]xþ'Iù®ed{NR>3¢l <ž”Oc° +Ÿž”ï2?òÿ")Ÿ|~äg&åS•¿ò‘¤||¯l”W¶Q ‹®Aƒå³ú=~7TáwC©Ìë§ên¨‡óúñºö„»¡äòúݧto^?å¬~wÝ %‘×OÙ+$½¿=¯Ÿ´ð)Þ uG^¿ë’üŒ¼~Ê‘!¬çêÁ¼~×\Orè*fõÓnrèÊæõSîšÈwqw^?AC.²úÝ‘D2¯Ÿr‡¤"TïÉë' GTºÕ\=cT#e%#¯ŸòÍ_ì™øƒyýº$ZÅž×OÙ-|Ó T +yý”·º’QÐwäõ“‚IrSï±||OÀ¼ß”×O™ +ôó?#¯ŸòŠF5G€ïbDê½yý$LM^V?~vü¼~¢iˆ ³ú î캞‚³yý®â^Ÿ’×O9«+ÉæõS¸æ!RÊëÇá·¤dQtÏÕÝyý”ˆ,Ø'äõS˜k‡%õ¤||Ve*ªóñ]I'§:ßCyýX*’ÓçV4ÇE^?ÜÃÕhÛù­yý”-yxãÁ3òúÉ­á­Ë“Äûð[*ÌùóIâµix-¯Ÿòy³0Šàþ¼~Bn‹w‹÷æã»-HC>ߦ›Õïñ||j@L×no¸ŒÕ¸-Ÿ‘úX^?cû"«z<¯ •RÊ+úp^?e3GFÆnÎë§œÕïá[›˜¼~úúTæõS{}B^?å¬~7çã» …+Ò–—yýîÃó²úñjy(¯ß¥+™ŸÕOî–³[óú)‡w‰V±»óú):‰|Jwçõ“^V?å{áÔçõ»ßo)äØí˜'™}åyý8Å%•ÕïîèAQ^?E‰àey,¯Ÿ²aHï^Ïë§ ˆeVä‡óú ;)Îêwa©¾ÉJ˜×OÞ¢m˜+7Y©Ìë§Ê†y8¯$/pе2óS:¯Ÿòâ ˆâ| –^÷]ËÇ’ViJG|ˆï•ZÐ7*ŠÖJP*ïÚU¼ÁÒt–1îô&Þòqð´oŠ©Ê,X!Ž1¸«2÷²ü|ìDKˆ}# ,+ÌÖ{Óã®ÎÒG¿ñT˜¾É;qós}ö¶nj¿(d"ƒ@­i5;VSb—ÀsßoqÝî”ðbýÉŒŸÆ1ƒÇÊ˕ݻg·ìö4ŸÇéþô—3gѹÇ<¥¬{œx_6£³zÙÛ^4æož]Ë<ÿÒ·ãwêWÛx/.ƒ¯ÍýzïÊI÷÷I÷7ÃfIZ8ƒC±“}ë~ƒñjå5Â$bñL£aÀõóÚïW7B“}+š> kÕ$4Çù[y]jMН!yÒR™y%ÐL²ïï[r¦¹Ž¯…˜ë0 eºe5ÝŽQCÀ¶u$û×êôã9/6tZ»3Y:}¦™°-}ÊØÆB%lz_m $Ç‹íöÈ–nurðèpõÏ A»vz[ñt÷hç„»Žf0:ÒšØåqšÎŸ3òŽøÖà«ÏŠP¿@áä·àkØŽ4ŒÎV±Þ$çf\™4Yö²9Ü–²Ns.Ÿ'ì¦Å*ý¹ÜpWÄgA …Ö$JþL\x¶ñLôɰÆp~”tpÈÄG3z~gë+òësèó‹3cÞ,@el–D¶¤°e6îeÈŸì#NvÄa™‹±PAwƒ–Øõ~œ±³²I;]F¯Ù<ý +dÖoâO»Î9G†€ø´sÑw¨ÛjVdÿñO¤í?¾Íè»S¸UZ¸†#‘²…ëé>3¬Sкùæ ÊuýZl³ÖEŽL6¦nÎÞDe0‘q‘Æ1Ó´ºF’ÿÄÜw?ÈÏ„F%îB½ù~„–gSpÃDéï'¨r$0£g“ ò=Ž@ýœS˜Ù—híÅ,à™‘‰´¬>h› }ãPÎ-LÙdgeÊ–Z˜ÑS+®3ß7ðüõݵÁ%ÎŽµ­ ø¶ xàt Ùty×ÄY…±y¢YSsÀY™¶Ð_ó jþÊ\ u…Wo˜¹qé`Wš6îö‰nïl×spªïásgÅÙªáŽà̱†8Àhfº=#äv¾d$ ãÚÃßý€5àÌ‚eäŸYàvq,Ð`{–¼R躚 ©CeBŸÏ„S¯Â²@tå‰]ŠP’L b5³™aÂ$Z¹ L‡L`*ÅøC¢ÄY²X éOXŠ,r§ö·©Bèx0‡ßñö/¶Og³W,vä_€Ç:Œã‰Þñ±—‹Á- ã´1Ûlι—ΛÐêæì²«o û÷w9˜xzüç · }…a +fæÓïÞ’£ýz0b^ Ÿ³1_ƒfhyæÌ×’›!ðÕ 5†óî=sE<7Íw3F¼ƒæy0…ÛhÞƒ&ÁzáŠNô@c`}‡g¯g‰Wmm c²Ad l6Ïe1Î:$ÒÃàëùA†óƒѽpÍ=(-]0Ù +§€æ+Û$!m05'ÇC¢š´ÁWìÌΰšwœ7®'+3œÕ’½‚.è€2V}Ç¡’"ÀŸØ;T;4Y 4ÖôX‘½ÓrvTæÑö߯ýnʼnj¡~Êš-_É…7SIüùu~V4’9ý¡3\š˜­r>™ß]Ê¥èIà_x›8GÑÛ “ñ¦14N.|Åm¼_#‡W€Lô¬CÆùÙa½g Šs¸k üñ–ììMÀÜp‚=ûôvÈð, ýi¢m9Ð'Àôº•þ”ø rÐùÑ%§×<úÄ ìôÛC{àŒgkÙtB½C°ž- 7ÓŸ +iÍrÂùS§|—ÏòÛ}ž•Üö +ûÒÌ@‡õ<ò~8R®É«1ø½653¯i÷ï…§%Û©1q5ô&h‚uÕ¼òeñØsÁÛ´;Žzíí.ØèO¼v¿)TÔš--j÷c•ûK}Øk´ãŽ;¸:4=¶H¶ffõf‰šÉH O‚±šN`” óyæF$˜¡]¾;h3†Î¯³¥¸ìáçOC‚g˜¢¥ÈÙ$˜Q¼CŒ¾Ð'–åÝÙŽ^®¼·Ûa¼?b+ìØqòæË'#,Ç!Nd‰˜|šçO3ΔùdV“ã¯û¢5žc+cµDB¾–C[ÎŒËÚ–qtðá…¬ žö¼Ìåó KPnq`Ô¿u£€fo Ó@)¶;˜åíÃÌèÍS° +U*ØYY¢ ÌòóÁëZêÒ\ô¼SSŸNX¸K«:Ö³r§˜õ-óÒdç8Gz¸Í\¤œaBG†P[ÚmY5®øÚ’9Ù3‘¦6@õeÒiG›Sd‘º~:G'}ùcÚÐ9Ðcé‚ÊØÄoEÑèÃMÆ\:«VZ ˜) Ò«è@¨TØ2ä[ÒÆˆ}èc¼‹8w¨)ÚhqÆò5øéã{"Û4ûÙCMæ„4ûí†{s2‰>F›DhE+OžÆæ6ZcÆÃÆ­rA©@™s«/½›#2ØQU:-=ô°‡~5‘?‹Þº;øç†ŸþâÅÁãÑ|`IT/­Y§;_77ç\M‚RG™wBjt)Á ©W‡úÔ™„ÄkÂÅ#@d:Yé2 Ì´’ŽN´\?‘fPÐ"HÎÏe­Ý¹¬»wýTÖ6.²‰œàüŸ9ôâŸü©8öâ«0úä/LÊ~¢cuöäOtìÅy§nwô!/ª“?¥ãObË2aÈgr21,øà³´Fˆê_ú·7Š?Yw©ÒÉŸ’sÌÁ2©” ïCC¢‚á#Šóf΀ï8Ž«G‡ŸLL¡ä18$~àÆ@Ò *¥ñ‚Ê⦮ t,Î% ”ê‘n ˆýó”ÒîéF3èºé(úrV‚±õ™†®A›ˆÃ1µœ€NDǵnL^ß8TïðóQ1„}›Ä%»¡’•pGO m6—°±¹;4koOíxof; ófæ—°Idù`ä|22=(cÀ@1?&c%·“# +cŠ$†1üQ3-Ìɾ¶ÈȘj%›ýª€ð  Nelès>2ȵ$EȘZÙ’öút•&ÀÄ­BƒOµî“nÃÐ)ÍJØYru4€yuÆ+µF-oƒ´j•Y‰Ö¥nä™ÛæÆE¼%‚‹*»knä¢ïä•6ì#.‚·"çÜGgó•Gb:4<¶L¿m66¦P© +mØòB%j3÷Å­øÔûIħ#ìäXÉÓ–WV"> oRrŠË¶áR[~FóQþ×\%ÆÿZkÆ™ÈbAÇSpÙÉP[ýìÓŠÚFÔi’-%„W¡= žØÙñDŸVÂ8vyh… +`{Šy?´B°ôE­`½§bO?‹I»ûY´C‘vl£]ÂZ¶Éoö‘(&ú[ßøg¥@¿²g¥oü³R ôسR¸µ[* Ç€¢Cê¡6‚ÿF0»n6&˜#&älÙ§‰2[{yCŸ@!†rWs1‹hžö'ײ@€YŠç”Ìöæ(Óá†ÂÙà1†´Dc!!úç†s˜öER%vÓOZr™×›ƒþù™‡.)ÖJaîhÂs¬êçÙÁ‡ÿ;^?éÒ³*Œ:oœü’ƒÓ0v> R¬ßÒ-ð[¦¢>VXÚUQKB5Ôv¿ hOpÚ&ή¨6:R€GmŠýä¦ ¤C+/øúvIdñ‰þƒÅÙ|àì'‚¨ ‡ì™ëÅZêÏ.É_{”é½ÃýcXN®RÊh©@¦ÀŸnÛŒdl@ Ïðɳüí†en LM-3nu“)›ß’ɤË-ÿÙºòàóiЋÎ=Y§Æí÷©u Þé„zì×àŽAÍm®Á;ƒÃM®Á;ƒƒj×àæÿ"šÆ)GéõŒD©1@I}~P†ûœÞ€Ïÿò©!qßé÷ûA©› TCø¤¼ŽÞô:½^ÏKWCx}8¯Í% áóN +ÀO„”’8N9) +6Ƈ;ýîA…l%ÊšzJ„Ûév“ü7ÿѪý€,æ½ÄÖ šÂµÏ祜¤'kfJAûéR/Ar¥ì»t)×J?éƒã‰ +!ƒ|$î£;„>/] +>{I,õ9 w²Òè¥àxyýN p¼(È*>7>Ḣ6q‚å$ü`ºp/²ïjxõÀCadZDYÀÚFñ¤5Þð 5Þ‹À.q5IÈÚ?š/陉fÆ LIºI(ÝnÉ-ï>4¼$&>x'5ô!àÇá# æMN‘ ¬@jšq lá)ðK^ÛÜøoÒ=ye@D§—dÄ‘+&ÝMƒä,@Âwý”Ó‡S$K3 Ì  ^aÀdÀ#²\)Ý.7Á“m¿€¨Œ#NV¡2‡BàBঘ_<>øCÊ¦d'Žf7/Œ<¯õôŒ PƒP¡×w.$¡`\¼Š¦A7T#ô¼%½l)š¨4€Ê¼$Δù<@ÿoº”‡S÷ƒ7Á„%(N¸zt“$¿Œž©`ú€.‰K…¿fËþ+x2Ô-  _ÂÎóJáù äÐÓ‡™n œaËI¤‹ÇèŸS¸÷…W懃f$‰JqçÜ"ð{^­žÜMTêö¹@ ûy•ƒ¹ +”%‰ZIÏR/˜ä”ÏO3°i27f7Ÿùz&ôóÕç&|Ìs(õ8éG E¨ÛÄósÍŒdéLPà1˜p +UB0wÁ'"ÀÌ ‡`†Û +ân0òþX9·+AÀb7R ÅÊç +´œÛ/”LЋ˜`Ä}¨ãØ( + Ið Ù‰Ùå¿ GƒîWÆN÷øo²ªAj­‘X’¾€ú"½n 5Z Ú?x ÒÆÑêîC à9³–û<$ì Ô[~V°H0 €Âª+ÀΨ€ßUãË¿4Äëô“8‹ýÜyHð Ôù'Aõ4SJݯøË$”b/ ,^l¿‡„Ë$WŠ4Z€_Hg› ¸ >·˜Ö$èd=¯gÜ€ò + endstream endobj 50 0 obj <>stream +ÁŠâÄ€“˜ë.á 8AƒýB&HÕå«%Xð¼ìJ 7` X˜ïèW@sÁ†Ó%Åx 8óh¾ø‰©åò¿’¼FcÀ­Ž@¨A­8h/ÝÀ/T¥s ûNIðSÜXš–kN “Äá pe@hA!åÊ…_Lù ÔÂ|²S©¬ËbÂ-4À¤"Ð⨘]0&¨…ÀŠ!é…‘_ìõB+Ì>]/°}€:‚ZŽßbTßíö™y›$Eóy|À¶õ ÓÌ +Z{8À¼¦œ~Ã_¶ÿ ŽC“<Àg¿±n Ä|O@Äþ q–eÀu~d +Ήo²#$)] 5Më)ðb¶¼tÚšR‚Þ>ÍÚ‰8m§^>7Ûÿþ/öT#šðó7VR0T'ßóÆ~òóúÿ}˜ü3™¬×›ãä8ß‚'/ßûùá¸ÙÏ_‹Í` øÉùu°1­d4ÿ¹è½ endstream endobj 5 0 obj <> endobj 6 0 obj <> endobj 18 0 obj [/View/Design] endobj 19 0 obj <>>> endobj 16 0 obj [/View/Design] endobj 17 0 obj <>>> endobj 31 0 obj [30 0 R 29 0 R] endobj 51 0 obj <> endobj xref 0 52 0000000004 65535 f +0000000016 00000 n +0000000185 00000 n +0000047379 00000 n +0000000000 00000 f +0000266555 00000 n +0000266625 00000 n +0000000000 00000 f +0000047430 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000266816 00000 n +0000266847 00000 n +0000266700 00000 n +0000266731 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000050006 00000 n +0000050077 00000 n +0000266932 00000 n +0000047801 00000 n +0000053181 00000 n +0000050498 00000 n +0000050385 00000 n +0000048830 00000 n +0000049445 00000 n +0000049493 00000 n +0000050269 00000 n +0000050300 00000 n +0000050153 00000 n +0000050184 00000 n +0000050533 00000 n +0000053249 00000 n +0000053489 00000 n +0000054522 00000 n +0000069362 00000 n +0000134950 00000 n +0000200538 00000 n +0000266126 00000 n +0000266964 00000 n +trailer <<64A8AB8E858948269A0BCA92EF85B468>]>> startxref 267136 %%EOF \ No newline at end of file diff --git a/packages/web3-rpc-providers/assets/logo/web3js.jpg b/packages/web3-rpc-providers/assets/logo/web3js.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3b4cf23de26173be4d1375647c4864ebd77a4767 GIT binary patch literal 80258 zcmeFZcUT+O);B8m#BswI8&eaCF<`)S(?nuZj6o726u>mmVv6X( zfCQ#U*aj?91O_1i5+Kv7=)H)moFwPXxo^4WJ>U1od7hi4=b70vvuD;?zu9}w+H0+? z!-2!kfD88wj0^xrjvN7?xj(=m6L9C(qd(EnqeqV%;ckATW54f?{Xxf%A3JvZAL-YJ z{C>x;wN4yAcKpQe^p6$)r=!ES0G=<7KRj{k*byGUQJy2mc#a&l07L*s07s7==i(RN@QNvZdFeYo zaV2##iCecH1mX!bmzD3{ck=P`5BTZnvzAs#6?5N530Ktayn1)_nx3;uVsa&oUsd1o zanG{VlcbatE(akl>t7}KgFSc8<#6i6$uEv`uNw1kuO2yi;>d6Mo;rT)Z~S>qoV@sr z;&-Qb#mpXD5?8wIqkQMSldpuiv)@lD7LO8M@m)zw>borYIJdIuyxR z%jGD~F&=;}fc5!L{QfHbg}`43{Dr_@2>gY>UkLn#z+VXbg}`43{QnIB#mypE%Go?C z{iW|WE*}C6Sti0@dtKl|}amY_44R`0BD^{h$?O&z`>d5VVA5d}o zA~R;XiUvQKVP5JS&vN{}>4xp-L?-e5teDQK>I>ErRlC8N55UXOWkweV@(LGA@W#a% zGQ%p>@{j5#jYXqFn&%Rvk(TSj<&ctJ{E~-wy5Qkf_7bNj#|9x`{8QJi+|B*BdVy!c zN-(dU&UBqhfEoPa@O70lf8SSfu6Ks|!YkIFrKHDOtjI`3_O!Iv4{hj)801DcZbW2n zxaW|z!ouk$=RWLQ{pp9Y$mLIOmt^`ZWCByFT=c9Z9Ko+dFJJ4xh`aJ!ssd=01xb9Y z{EF5j-l|X=4*!~PcMy?Ue>%NbW_AL$*xzh+46|9WB7Jl*)OPcogPb(7CG=HIN8~T2 zimfGsiM*qgl z#vj%Q{5z9(d^Ml$ZR79Dlx7jN5@IGN zC4BiXErlUoLDW-@_2>I0{8Pg8S(`k?yvQ-nR)&EgR5oMSl4;HmptI|9^+-ypeBDo@ zoH3np^$(Np{(H2{a{y{B<9zu=co4)UIqXqMc7<^B+!etVmuCjXUln=vwjIO9c0YN5WaZ7< zqZ2+=LjA24FQRajB-c@!QnAG-#xupD_epncBr7dr;3=4mFCX{Lol9YH9LR;q>l>$M zTnme^CDA;+RET+J)YRQRKj>J$SRQ6t)y%|P@J7dv{}#|a;QZpZ(Mvo>BkIQ(kfG1V z`(aEQ+@5BQjQZXSIC*PBL{Rtgn08{%z%KvLA0i)}-o3o(K!?Q%ms-|G71Ue3K22B3 z<9o|LeZPN192x@iJ`XA=$oIXr;2ccRvO^oTit?ojm(@^WeL9h%EjI!?-TA6)RyspF z1n$79%)S#=mD4t2J-MkD=WHGTS;*=SaF|lf`uuMJ&;==mpQB_`t{f~;XR8PipT(3P zv0l~uBI^*)NkCncYW|+8^an0iiWhn}!|o&~b@!PzSV_;V3|fzS;$)6{9h=2Yv_z;G938xXKHKHbAC1XiEZ3a>~^&e;Lg`ZDB?kb~nw@r_z$ zm?rIDUx%jcQtM~O+75oP7a8*PN1qncxu|=$)h-jFAfsn5LG?1+tqlsIWv9 z<-OdZt_$loy7ZM){qR~t|8ad7)%u#ds-tBsOZ1dK=W^S2mx2_&%c?MTvT1!h=MbP# zn%TTyo2`VP#h%oiqwv;p?Cd9C2NlCN%{8LWDU_=p_YDeHYq%|r;w6sFUpxeK_)XRl zOzqM90m{4PqKAO4;E3&mr+#t!b1IMn->E~uO7Gw*YBFjz;}GzXF@FeXz9D+xQE@Q0 zy0u3tJp`OoIJhHq(7cA)8+m>RP&PXR%urt=hj0&k>THOQ`hAr%z7M@>s;@vo7Ga)9Et<=8kH@VXst;71Q9y~P%dN~=J zYBEe*&BCLfW`u@Jm~t{QpNV?d6=DMS-1QCtYTA{D0Eg%@RN0#>a1}6;N=F<5-1a`A zKT{r2SNDON3c9n_?hB}5T-ItKwG}-dnQS*Fvt6Jnh^(3F+S1^$X?bL1D+QdL9Pfx^ zBI_uhr+~+b(_Vz%Ie`r~Bw`N%tLf3K+3GS_ogoHqrkwEvR?IWye$q5;ja4G6%EWK6 z+z>Gyg>gxD#3i3u7~YYE2=%MB)ob8P+hel2+^$_yf9{Zm>1_ExJ>U28f6>bSsj5eb z5yh3ng9~%i4DCt@RsQk(xFSjccu?-xE!`xD84pBs!Vdu96ZN{c; zQHW?T_=KePrI)YofQ;{bAcH`HW(j0L-dO$*>Mn4btOVYwZ=!=1{wdM9l|G-GJp|ko z^Df*V_l_iyAtL&vX_H;^_qGfcB0DFEmfMuY8HbM0dmrtxbNr12&B99>8-$&s)>7q` zKjws#7gPw>D;}_G(cs6y75jcx>%+rubgOZ`;}Ob_pG{yjmX?%J?qsSiMoPhCM7JZh zYj{iz$|(qQ@qtNSOuf6FvJnYNZ6P|&jn^vTzW0>PB|2Mjk}DCnZgGl^n0T zJGqs@T2I^c8pzZdAWL|_MYc}bLpUK-46Q?e>3KhUQW7t-vt4i!GhVhcl&sLX;b`XT zQVK2W+o;WWvb@8hSbY?g`S1Z*)9GwhKFGtvb73wNr`Q_MaFA!6aqSS$nz)J1iLU7p zy&IRccc&xs*t6Eij%NSuzzwWWK&=Ne1P?87M=C2T1FLV?_;h*v-cS~NBJ}#s2y?Do z$#T2(BqOiU*uJY~q!H7QSDT**oFR6Xf^qbj>2QG;X@xrqFw|z}tpnug(QpGb+RXAa zdd0_F;Sdnvs`wi083aw!ZCeHvsaO;1Syhttd)@`5D``1Dnb{uu0T+1)Alcwh@3kCa z8Ru1IcAeRZ7{Ypo4GT5b=s%IuUx6xp<)h$Y7uOOxrD91PVP%{&cAm}2@?jvK>4Jl( z>tG#~&9*^UiBlf!K&%39zP!`1scXgP&fEinDwg@m_C2jOz$3-O!6?EDOFYy*7eiio zPzyz^E>W5DOH%78_%Y7g4V8T6GatydOq?fp@K z0(3cNs;J$|;PW9MNgkJOX7^fO-*&VcM#Bf+-fE=RN4Q2zHaa&A zPp~HWNW9o^BPXm#27EWKVo1YBZ?THM#|oXN?QSe$kaIQ8{E z+l~IIdeDA?)RG8Ybke7Z9_s_+NPwT^J#+o-)^qe$=LVPl2B7+b+?2`ik21wGWt&s7 zW@|Lay#eV_7}2bOxCjp`k&2xA(Yvsh^Jrk#t4CY;o>w~~rc_S^Xco9oY9Cz6u#JOC zIP+PLg%4eyTJ<^;9aB<1{Lp0S#?L<=|EFZ+#w>pfNGdsd`qNz~Cn?|}*`=;5Qc_J> zFv~h1ow!|>GG`I~v0p~kYzgknqRkF{-mX<#cKA}1u>mRAZxtVF(_My!A#__6`F0x= zj!bY|rfgA*2WMBES)OgWCk49u<#s(ALoh9rn*EYgx`G$vLr@>nUkdcYtDib8o0BKv zSKJLXN@(Ghn5)`qrB`CpW@RQ}oJ+QW_77SkN?mF;Mi~xioHg~3Lx71zRvuDOIk5*w z@a7y_5ae^JyY+#DKyJRgH3@h62yujGnK`Athyu3t3A1G3>IrG#8zhwvTWVR!Y zAtD+p+!XIT;+oShZ(5cSp;^NsbzXSb_3`+Re+Jl~%{tE>z9IQ4J{Q}fDl+RsmX>rL zem0_B&lDAOq^vK*yt1_Mm>3S(d-+KxXjmwIux&6HtnR}(OXXKJzm@B}xEe8~lN&V4 z7@p;wUt}9CO-C*!lMk|eQx!LCA+O4nJ59nCbp0^boV|-NhNi~QS}+NFH?D^1-4XVw z0-l}j8lPV^AE^Mv28GxS90FYWWaU1zA8hWlJyka6y04<8X)kjN3(`q+4Cgn^_Y9~ z$}`l9-3$KdYCMSpRh^-Az{y5t$*a=B&_Z|hmZx@6Qx)#2;S~Fxk1-j7%Eo2A^RGYH z18pW-fpSK%P>#?18d`D8#@zmw{)ZG0ewV1T>|TL!DeLXoVD#|fccNDmN3?V_)=A&~ z8QcG}@)1XezMRG|D^&7_Lx7E3Yw30ZP$2&5?{eZm4v*texA9{HR#kT6G9;YS3$A zr^aZE7h{W_=}ojfz)1Sp(e#J;E}i@Q-)nvBN3m2h9XF34kcDq6X5w7KI zWAjokXLrrEH$LtRA5N4qdYlI$(feFS(qt6{*}ObzZAefhooPb0qc>fQB`h%>_nj*x zl~8}8RU7zRshho|mhLd$Sy|z>N0|-&NR}!IOOoDX)i+gQgIRb7jg~3T!rH-`;g#JZ zohUV=BG(LlfwCV#PgXc*R=yLfQ%ybu;8k^MGb=^iqdE4v!D)v8&B5@%D9a6ddq{){ zEt#guM+lII_R;Qb8A+gnf^?QbOX}K5B_;lXHvM=8l~~x>9g@CVLsO&*JK@VLE62pt zqR=n(g2N}F{|UpB;ND>mn$9Is*oasz^yGFvYh59(Yr;aDA z&@W+h$Ts@ni;*qEq8i!V^=^2Cob^a8x**q1;p*h#*-lNAPm9XSZZx$7C==nCs792U zH#TewintYKv*MLv8>!F-N)(c3Yc<|l+w<}@a<|VL7InNk-DYlr^YxiL|DwxO-|s;j zU)!5or|<{B5S)lKde{LKb~n9se2p4H3|b+Ej)yGq#Z68}dToAF-mAYMbY6j>NJdpp zq`lyv0wPM$*Lt+rs31fheuSwvB=`KAN>{b8$UAWkafK1Zxgp4;Z+i#kQog+($gG)<;Xt1fU;g0_I(}^4x#9+I{+?i2;O6}) zfsWv(qUh1<)4?hU#%+Q=jrS;xw|HY#qD#k38pO>iSJP8s7Nb*28H6%{Se$iMvrgYW zrs?{}(k=M4^uT8+IW7JPJw4{NZ6~z3v*>sg1MD1esH8MS-1Vw@VLVQijMZv}`%`7p zZzvIa?O$t7CYF$GrqyFeFnPqNg4;e@Ydp0*nqu7mQM{Pas&iuxw5i_n8X;P8#Y;i|vW>ImmB-^SaTp9uq6pbNvn%k!gyL>E~(C5k13LDqjB01;R(9WwPw2`wMW)6LvvhS$fy;FbQb{f8z$7;(Tw6ii zbB05ME$#WUmf7WQWQcBU?QG3PYh!qAZJC3Pj&!?7Yq0y-nLeKkg9>xu0}5&o&TOrX zs_~5G$Y=VE`7pHmk|QD_==D|8{^ccgcDRc`*xrj(pyzaop>LvfK?0;ZEVHC!T7Hg% ztt2ibZW7pPgu;;YtSPq$H}}SlV5jETbDHDiy9Kg5eC5tqLRoNBSzr|UZhZI8dDs6d zK#v;CoPvZ>sR$;^e_SfzMpE0D{c8*@5lgX}G?fp>hcn-UYIX*Mg@_3nD+_)@yy>@U z0d2Gb%2p&IhRNjPRD;GnIWRU7H=Jdhz9XBuQ+vv^0lZZy2vt?Xg-13RfC@u*wiPZH zhGf+)4rCOdJkBKqNHA`ASGjpk6%!kbob`j zh%Dzv{%ZW-RylCo`e3+_a0qB`@~BSyboX$jCS?~3fawImIyrUPlsO{DxF^0Y@c zx^aAEd%W~Y@b(zBH~V=Y9QyTtrTM>b?tlKAsvq6-8W1OkN`KmQBWbw2xj!^NomDp4 z*8kO{s||OGzF1kg5Q{CsI;M{ER_ysnj8M) zyf`i{olxAm75gF_Q*8WIgQ|{u>J)R*t0KO~zDK$G{)_4xZOV-)8)%=J{CrR z<~A%g5<{bN=BDdV#XP*#W<2G3dU{GlYb`$lZomszo`DViJ934>ZE$xQQ7+Hm{hRXM zSDZtD{xLDDF<0!udg5JMkxsoBH_A~1);Tpj+=`%4*}WhyTWX<|=GDH90)ma-%c>hO zCsq5y&wY-|Z|o_lO{y(`%76s}4{DNETbH3?n~I$#3iaRr{9nSW+0i=HgSM4bfX)}x zx4G9Ux4f~3O~+#}UmR$3Xt&c9o8sD|oI5fup9ySBT)79Olq=e_gipESl|H}AfneUe z9+HhV)dc8tyv|9WZW?g<6mu|QqAoiGyV(iAgp?%8+FIR;@-|q6lh`fkhxQML%RA9N2 ztl;MJylv>o(eU#|0*I5Cw3~*J7z1Wkk1#Z+HLO!lZ)8m^D=#EidCd2R{}NLG00jyg z50i*njK5107GyNY$OP%@gJaHLjE>3yUiqq5fgpPAU4HEk5e63a)h0R+v0wTeRY7Ci zxzxyK+VIBmwb_Q+t!JuNkfI#|2vg`Lx~K=_zkeT*aVm zm|(9DKdJgB%lZg#hUX#R+?l4y&>x!G8^TIWwzeV`2EO8NR~+hXMYJnw4OfVhk%|)Z zQkqa_c6M<8a$cgUg=3{T?TWv{3{qIF@MQH_zXxr0Y2|`+TGqVcI@kW$6RA*yt%s6C zi`xqO#%gYCPs8u8s1n@gc@F`b&W(XVQ$d~o4GjOw)BhixSz;3vF;#!$;7g8@--*Tw z5#9?=e*7B;eyUXfl&?ovrBl^drPwAMbv`cwbVs1v2qwuERu$INFuM$k&iv@CZ(moZ zKB)Cm0jC~r>DqU>aALP0lU5HWavbYC%(|_vUms^1BlF??9hYt_3 z0&THoZlMp-to^io>jcVh`AI=~)9N{op{DCzeN-_8j7-#^c!W@&xd`*d#~=Qt{GT_c zPB$EJh%gQ_TsQnq)INTkS`FC{NOfxxtg)!XtDvV_DQ|`ugHCa5y&%f%wgN-1!K(sV z2|XH*bGCI)WH`0zdeRIh^7r{TjSV(p&P~l$gxoM2SrWUT9oVk%JUusk&2Rv(yw{n$ z*YRPPNIyFd*W27?tK^eIDK&!?HBAAoDx!&sA?fa>w zi%G%hz^uM|<=Cv?WgCn%q{8N2K8WP2#ugK|l@*C|7om384Yq_Jb%zh8FjV4lC)*aK z>fWS(2*7BW_FRtDGZ;RfRd?!%Uv|cl^U!>;pi`fvIw2xd2^zfhW^2D%i|*!@WX~q` z3doh$2UWaLZPKN}hoEpBhZXw$1~<#^AQgCY+Hvy;vR)>-2hh%MzS!^e8oH%z=|5};qA6|08>GJR_u5bNr2{Rlof%`ZkX7SV;V1cS|vQ;ftgU*KZnKV!2aY zJQY_Ea(Bj}Atik%d9vepX7_syl*n!wD@13UPpt-S*d^VF5Q&tfz?q1x1$Jg-n|3Ru zF4SKDRTs?|Tq3Hhr>$pZm~JkKp1eieYguOxSCH>>de6f9Q|RMqLlwPoT1A6ZR&s=M zHoG4RQR`0!%j2P{k&53Y=oL>UNN%VgZ~ATVk4IQlf(P-{JJPzsO%?Jzp4{0jDAEV1 z0A58`c{@xN<0AATYVAcE+Z^i)cY@UkPN?jI!009G!lyx5d<4Ls?SzBk;u2Yy=giD! z46dr29g~uxR<~*_-XAL-7dLD-Et4xI=3P2KfWvLX#6xm;gs0rXZ>JI!=?J(!oTssK zGb(C{>rECDZ)}JBKs+1ppvYJDhK+dIC%qQuiLyo|*)w;^4d`o{tGmc6NQl?@CVYqq1s*H`GRSq!w0^3TM@3 zahzgN_szQj=6){V^77uY09VlPS=W*B#kk&EF+)aCYYsSB!(iQ75tC-+9(zm2nPw|iQz4Op-dL*L-_tq8F^tFR?ytQ>4JzUFBsl3l&pX=r=`KAg5PGiuxt(`hpJuS=V>hIm{gewPBQJ>p`$nAlIbsNaaN3 z728W}i06Bi7j>(IDc0B`DuXw+7{P*mHO;55%}dnE+LlPCMdcX3EG944Xm($ijMsg? zTWJ2O&4#X?p%>QaBdXDcE=kxJ87A8IKk*|=ue9ZRY-0r{8re2BBhzx_t1qncM2vD$ zXiKy8nnGXI{GLSdw}vkfWI_bNP8sj)YdjOwB{5{T@1%{cHo=Suf)4Rktih2>or|x# z=xcEhbBf?Z-2Rq=-?@g=fS#P=OGfM@A&wA!2i)GXgA|@;QQTW_q{Qtd=vc)Xc zk4*dSW4j-ZrK@=+Sjb5}=BcIIEd^Z9Owqh25Mh>#Tz0p6-Xgl%*KTUKJMBhL2ObHn@%`ZztkVxIueVoUCfJ>7LqT zZ)Sx|m&(@V_UZ`Tde1=fkOG(f7Xnq-6kO<4`)yfO+2oS`2(|pUc(>d z+wsqzc}@dMRehY$wx-PP_R1;xj%B4X@aKtO=oe$*Na(Lt`OaGRWIhrfJcs89Sn41{ zV#sAh-Nh(4(D>&)x*Rp4%In^z^>MQz=yj(Ex&sH9G?VP|EIsF(UvQO-g4^whA*x+7 zTg$A7b^dfkec@JZ)K>Mur6n6f`mp8heTTSTCmkRKQ|_eW#ZH9E_LTD(R7TP$$%td) ze_scYC~2x5OPdy}qm5Jv61xt9-)Ln;FsedeCGMfSBns?C!>?$R#8#AdYa9GxBi4&Se7=`WY1E` z#!lB%QH%Z{fktrXaJ^(KRwdzQH9MUU7|(ArO%T4(<%Jm5&``g#@M-w~$=hdeR$kDx z1DG7Q7Z^9)ONbi}vvI1NmsgKjiM;wwC6ET+Pjm!zj!)>Sfh?1L;;L`oV6?0n~2?1`elJ?!x3><&+= zU8cF(=Gvl9@PR^V=Ydm#V5m!uf{veVtzAuxiS~IAUqw`(TO7M-#rfT~^R#t`8f(o7 z{go&6?8zPqf9-b&s+?x)%C)!gu%WN9&ZScmIEYQg%b~exN2T20YAv@NUbkE^uSMZ^ zx4>WKLyZcsazv-55M5eg5V4U1H|=3)1$xRWb~c8gCo?ne*rx&y0V(vfR!7mtX9HWo zJlmdv-K{!%RrEIIicsle)VF{m@3Eit<=``gg*rixuqI7l_GaTVx4Q{$YA&w08FE`w zH_%FO)Iy`AF^Tm}dIRV5Vo^Z0Lc7qhIK90C6{yr!8fQrgWk05g)Sa?iSr0OG+QN2`z{HYj0~~#tgsFK^6%~FsEa>@X1`W2 zd_TVqED7?)xGLQ-E=sw)Q;TJ}*-2xFiP)q>ViWsnyQIZLJQ6-B;zH@jG*Hm$N|k7F zD_lJU2&1yIowxHscb9~ZG0sbR?vNkbB=Fcr@@IIiqI7Yxhk)m)h{A1m?7=33>26(d zx$#*KylDV;DHSfciaFh(L(ewoI02F~@l@5(yI37a(%_#W;`9g2%)Vb=yzypj3~Le? z>)fbc>aldWJTDjzE;BJ*QQ(<=mtmZ9O{fp!O7<+6_h9r9ufbsqsYVbtr9!HuL0tU8 z-*x;yC{$Fyz#}?ky6xkr^2=ki{ku754bQay_CUeJFkRA`J%ID%5O7uF(Fhd%Wz_9& zf4z46^k&+0?+-eHF#OBvV09rPUQK{+@BXy4P(V4S{#qYvUq>=5*>R3h6VFdHEKyQZ?GDW|vp|1|uId)#f`OJrGZ@g z*oco=$*_3mppFWmU~|n^6t7D?$fn1J#uwH2uQo+0Di)Ov2SJ8<8;xUDL=4jUPH3d9M*>ycsE4fIZ{jUby0birK2!YCJ%A?iji$-P%(612*nn z6ms?~qN^%p81XB5viV*X7B>xc+%V9FSn-%^Vs(qYn|d(s(is~9VTrHIgyHTH6~{G! z^$fEYLX^f^MufMb$2my$bgD%J{XD|VU?L~wDRsVSvA8v zB(^Ap!+7I(W}f;G_MzHbxbOxy>6O|&%7nY8Wi_2Q)nEm;A!;(ld$ahd!aN_wT2-1a z5S&t?_PRe49L??@0$vc3{baG+l)iXt;i^FIk5SR}Z`{8a9TEle`=`mq=YU&1cSfkh za$W13!snRne$jEE*3vBS1)8mzV+D*3w8%%?GwiJt)mUtok{Esa8+Lqx{Xx~WqJ13> z-<9sl!Q;ur>pmphL6o`Ti`86< zmr7V*B;(82EJ>k@+YYlzIuz@nIIAfapM?Z5LG;f%{m*BDy=LCTqkhOM#%Q^k$ZSN&3+cHeuV2eu#I zi)>ZPMx!4(e4{835h#?B({WX{{}AxVy@C^WwI#$h{gw%ckg06;EMccShO>l9ZH(#C zSpF%_Q2#=MDet%7im7Re*sjP)JI7N6V(Z!n2;!>co-q~qY5X2<<(uEH!!jc7; z^8=#k)3n||s?mU6K)|x?Qhi6#x2(YrPQxPuHj7H(30~0LhxySTV{l{reMW1EA-0!% z9^e-nZwLK3b^F%QGaHKioGAZEVMMyOTp!5jr{HQZ+g$zSIZL9McdCfecLsfyd3LQU zGQ1gfFBjbwP18HISKe)(u@!|j(F_-hf!ZAEHL6{tTH1D1Q1ndN;=oYe0y%95*Voar zX@8vS%D)k*AX?c@f7vn>NA2gmZ-P@>-seC{opW5ggTjsoHR+D_s;2h9m z;+*}YfZpuGJqmQH&y_J)h*ESIzBRv(k7BKX3hSkWU59`C^SnNDSlRzr`GEl`ew%TA zSDPAA6FME_;pz;_GbG@Q^)DjiY-^wz6(gFipEt{I>+qBgg@h#rlSP>l&>>G0v5j}d zU}aAxq)lhqbK7TMnKx0Y+I9_vUv!u>Ez?24`VAKqO~86=WsyUGROncI53ggaLM!hg zwwfk*YJIZjS=2gJ|M>RPr^t}p%Fc>DS&X4huU>+gqtI!3jiyI~nE2Pu5HsEu|M)dQ z>W{wYQKp>jSZYZo3=T_v{QCd^BeKaE5ufNoiGIK zOTngC_b>Rz^esHk(0R2yWT%zx+XbZcSt=t|2~)JD{Uu{Zj$C%v=64_bR^m{+;b{FJ#qX*2^=^KL(t_30O~3*_K@^FjosG z({oW3II*EWEG&5@K0u2G>^C5lZWg!C1hcM;HZ9b5zR8=k?FR2sBhwE7RuApWlXrsR zP&La#SIhS;$&MkS*t=1Ur~;Cs1e+=fN19nZ;r4fS;dz?P7ZM{SHM!>#y%U?8f-@lA zdIhlDK=|;tTj7qKi>4oz=L?-qJVQ ziga7EwMd}(eLV`%E_N_%`s`-L+khl$aqKLjHp8%y+|;gs4nvh!(t+jB55#Cc_j6?| zLob^-J$J5N{Sd9xqR``4-Lpq@+0 z#k`qv8oV-kTc*nMjR{)_0RoN=j}w(TpUieLOTB`-oD zL`NEavmCc!Z$1()Y{ea1H>=bi&=4E7d{gl|2R!AY-QOLuCwIB$q z2}l3o(#$yDJkRUmjyx0ythyETh0Ua1qNVrquRdrze){kRaLpPctIQ3#U$))ZSBc*X zWR?Wxn+{vX4Wm;-z-T|y!r_MpH%7!)TymbD1FmeZf)RU5J;K)4#N6;%FHiN6@$=9P zG^;X8X^Z&H+iSzDg_lCu^Gznm5OlM30M2D<MX(mRhVBa;y1JU8otsUehc?uFJ#4-aauG>leNWJKhyoC)Q)bzE8! z2!)IPo_r0Q=bhw!(pqAW<2wk8lfWG0ktG8cV!(P8MCA* z3;Xd;uyg-?W=>J4|K?i-iye{kFDLk)a+3MJZnT9>=N1{1!*4Y63}+9!F~i-0ghHm|H7s`B5a$9^oSwpZw>IzNE%$5#p4@UE2)uF??*+b!CkRf zOgj`3ql0o!Jp>5p(F1p>C8+44y5|FE`4#!bOf5;gM&T-XWR}x(0;^zu2uPJO2{n7T z%h#V{YO}FevnS##BAIHT%J;Bi>$!Isv~*whTnbdDk7f#4j4RAq^;we@tWIcvK3b~) zjN7Y{bB5h>h9~zL!fVQwdO~*e<CP5yNE}L*lcr`7Y;fTVbSwFD2=OdP^qT1qt zeu)Y8d-{bnYd6@qM-zVr^nYFcSBxS#a<80kc`Ki*3!XctF?kb#-NLLz~JL1gJtn*s%3DS3^6e={wsms{-NoS$?7w# z3)K0uZf2P-H6~z@U-WHCi4l7Kp9sOF2~o2U4V{m)u@8&Wp{jh~3}{)e$4y(cJUOnD zPz~SeyuLK$-Yed?%XNZ1JP5kf*ALEr7rs+ImNu_m%Z={07_1Nr@u8j4qQz*qt3H_I zl%>qbF}fn9lxM#9S}JPO$1jLrQ?M(%T~|f-Zt$jIVG9$~{da62otv28iASLlwRSn( zLfh+UHKv^GMQ!5wc3|_oLl#)HjRtfE#SG_$MKV=FHlnfeBiEF=pUO_`SQ=wkva4Ps z?n;@qRl&TvAq5ESBF&<60+f_VmCbCBash4XEo8+R7WKhYL&{Utj9ogAYIsVyZdu2t zP@T)@=d-hqji04GG+*vbj=A4d0B6qYYAnv2Isb>H{3~=i27*r}8P5}#l|rJz4U-y@ zgEQ@4>0DCCb}uOrt1}~FJ}fn4Zx|>xaMy?C7O&6xW3mE6N2z1nw2c*;4{N&I1w1>Q zn`mXl^RbRC{@Myg5vCP74?pK4;Ui82bRnI(0~cga8I?*6rs)xh32)~k?fY6O1SQq` zckwlYx|GHK+&u4EE8%H<&{j;G`DfBHk%8biY(A(p^_D|&PDmXBhT5!`HgLN8-GaGJCx9RQQSN!xeLM!@GVUZfS7yF;u#Slr$^t#zgdAU(<`Y~8*HA95fn5>6*KI} z)5kI^p?D20jr2ECmXM~KS<`quz3^Ny@#;_MtebzdIso9-(CNwf{&J>*XOEG zIU}|^O^=#%W1O*SHS|sR!jc&!lrgsvJk=<5mL$EeTtp1p%S3gIkBn&P2Nk&Ef^Zdl zTuSDp(YjS35c6S4kV!nWO#moLSe!fz3@;pc1w!NNTPl8DJ_xL!q zdRIWhTE+4`-|J*Ne-|J33Cb?fcOYpF`Zd*8(Lm+p>Q#zjEvJ~`3(z*b{V6YRYklg)b#jgU|b0?wCY-C+$U&bfK|e4KL5oR7#$eT@7C-bfPWBkANmRnybA ztj*XQUJ7fdNY~&d8+dY9x|?K2#|h53H|zE6UR@kkeRjKcA9Z;N;d{o{@E}=qPiJvg z4IRSSAZ>E%&+W}*jfFZf&AqotXVYHH#qa)IRjy|(|7M4oip8>_1hs3bir`Oaq(!Gkp=B67Hl3Yp?ozuJ!~O|;b~-Utv!bK}(H;;&!x%lfSDsMQmdjn} zczPxgl=*SSN6U^Og`*j8LISfyYENE+iSN35z>P~b$ApH{ed#?_`|Hp`wj_6zny|Ne z!NAj#x@V#}i48Kr{Q_IQemnipwnnNK&Oy%ajiPoXp0Fj zP>%6yE4H&D;;l~KOnLt>6{$`Us6e#@sI}>)G(Eqp3#uGPKg-tYG=vlqvF;5jLJdFu z38r(gl5H!UniSgv*VK8S@`G9_nR!Zto&~-~4EM1Lq=ji24!br#9L66YkOfRSTQ${Y z7d$`JpH}X?kpqUo?Sc8u0DaAcd1?cs|sPr7WEnJW2q;oB5yGjqS z&pSB-1Z_$tB0Qzc`c+eC(-_NovLfehF?9M8Jl3c5bETWD7xo$>l`LGD2Qiq1dy_D@j#UcB%cm!XrlJNircD>8CJbiJa`e>gqf zUMduNzZ#KHGhdaT_@R%D_p9;1MB}~C0p>*CLx8SN_LqFEiILO-bX&;wyy)oU66`?M zyM&w%?XdJiRz=!PS(C!~_Ab|>LSiZxm$Y^|9*>q6PQyS7Km;67{X^e_0MQx1UM4wHp4iq;#w$W>YH8boQHJvy$~lHfZwgPR5h9lRE2lk*nfi z&b7@c*;C4h| zAky?NsN?VA^w)1PiK$N}WPW!_otl<-@f4i`t-7A8?_X7CCP2^iE-4{J{Rk)YcjMRz6A&&z zWp+!_`A{Zd5UGLqH5_PXL~FkTOwd>CF>ava@w1 zCq}ouO{e@oLoKUGr%{KmjWguqm{Xl`O3M3^)PIQ#6)i9+~r7A=g zXOQCWd=FFEjk^Ya&>cUp+P`Aiqe_SfYhf!gn`YKU(6;$w0x+1$U~$HY@z9Z!*xnw} zaJl_hSWC-3_L@|qZr)dOf4uD@H+LV-pzJl1F!AH@R;gFsy7`8E$hEh=ae1pHNmDw7 zF`_-6?^I>LKKjtG_DNMMX&UxfDCa}SBd3ANJ)%0!E2CAr6KsgHjw>XD>F2?1a8D`O zJt2NCa|hO@wiqAd8R6!aJ4ijMTTQ8F-9x*!wz=NCd-ktWLH1vIpg@)P?Gb?~Q<$fM z=Hx!XGP5>w!7a!L6EqbQt+g^DJZZTZUZGy7uREQiJObm~eANBlHS_F-Ss*zH18YEzS>|YWnj61fMs2Ib44O(_r0| zkhYjfO0rTtdgWn+4&QCbl;{W{LXd$tQ2EuYSxbw^eVENll9OkYgIBwU zp}SQE2j=^D)}&ggw=cTtoNlME#s+gn#hew^zh`ilW1@_wOKq?E?}FgL-;2}-D3)dE zk0i2-cU(aq60_RpO%=dIx!mUwhX9&~Rbz-(W4JYBO+(G_Bm3uGZTGa`S`kWrDMc-6 zUj_Y~PZyiOM41+ktcf5LOjlXgAD)9yxhYQA7#rvD4kQ`~7DY>JF>4O^X34xGvVyO_ zd9U^7On^ULGIyd6cP5RjWDw5o2{zg-T0%!Pn?o z?E_(OjRZWY`4z2RlbfjKFd{0)ob3^a8+0Vs778_3--m|uXGO&58GsxWI5oWv%uPnn9?&*u2N8Rtdn&DC+o$4aM|kx_N@>8B zNWE=EigBY!c7ISlMl%K$?!CjB%G!Qmr>SEd1_9~MfPhj(nv}rINK={!p@gRN5FpY^0yyJHl`!<4 zjFbR@5P^h9R{%p$7=y*^W=~yx)1R?|q-^JKwpEf9x#w<+azk@4fcg zd)@c%_q*@+{qfgDzG#wb;BhqmJpbNmJu~kkPayBNPdouzgT^$D%kwxDd|dTt{nkbj zOv3B-r;eE?Dn!+Sm}sKx%O0oOIsUrB<&fWe5~gbeA-!Jd54MXKJ3p{-@ zI1$lG-StKwg`*LJ76Ivu0yg>iU$%acv-R+2l9TJT3$KXebIqQ#bRCtfSW|)@r}hf?XIPj@-XtW@7b?l9HNr z*49wn$GC?k?Bc7H#KhwC@5Zw6Fg`v}!^kvKDC{rlpc<5;2AcO-P+L0e`FjZF<75*1 zLSR2}S^7path7LJMkb(F#ZGlg2jOoAcA2{=^m^~!EZxSqs-^W-#j8;%m4yCrjp$K{ z`GK>&+j%2iOM{E?7(quC-6N(-qJ;@-jTK*LXxbqE5F)AN`WL%$xw5D2sxi}Di8x>u z9XgX@Zcec`kASg82t;Y;=)_ySXTTj>@CprG>8FLZ8^M)+ft9(sxfkbg2mZ$0U#`&B zqU5BFHqYy=qd~N^>ItY1*A~-#8)uivmOPfsK;E9+5sa`C-rh7smfrPJI)D zxD&h1zIS9Vdgx0Q{7dEI`ae`YCNjqkxdrb}Y{~8R^a*aXMw4f?VPRZ5~@UT zr}c|u6u5kkxcBpVeK<2&TcmEoB`4~KNrF4*w4GL#nYA#s01L(WdFParJQ+Z4w!K+s z}pFA+_7$bD<=DrI>yU$vlrR>*t#|~Cw zn8Uh|xbBLnj^#BLd3wCTb0dy)&VA0z<_wDsIeGZX@qn)*E+n(9Zt#u1V$8xScXca^ zHnM$lHhggRRXa9eW}^I6RP^S~V;2XIn$2{#LCs#-ekfBxO%8>Vrm ze}nZ486)$Jws4qq{H2iWxXS*A#{(=O)15cl%`9nn_W+pH8!6r1dD^mivzX9eWv{aX zRFuKZ0~Ud0HMQ@Wn0bepLS~qr{DeES4afJ^Ll)<9#urS$=3NnTHzJ-rZ~1YwL`pFf z?ikq=8!IeY*BBKshH@^}enx6mV8nF$Ok=Q4l&PfcTJ6FB15{4@gN5?}Z-Ws1D#t2X zJE8}wWnxbauu_gI#A+w4``2Ay8u(;1G_O7NKXICB9{iB+IlzCEOC9I;(>1!Fl&n4( z5i&`RXzOh$;^NwRo14I3+X)Eh91xLQerS>Wtj@k0CTg<0oxh#W^r5?kP3u`D2F18+ z>+~CK`g9b!Mpta5nbt%mkNS0mCyp(r;n$izO`*SzsP>c9^5#~J zIlFatviE-MH{E*=?L`75%iEFdZK`X-1}QQNejbDhFq^NnD=P0c=T1BQ%%(1?LGVw7 zfWZ72o1mL&I)rb>&ah_|{1sD&seh8d;Y=+HEzc0IBrpUTdv_-vPw#%Z#u&hyIob&4 z?i_07V=o`d(zjDaJBN|wD>m_KW7yJE&s5jQ!~Td=B_ArzTLDQuv^I~KS2ANam%^%- zYqLpOqQwC&ucjc|8THLklIp{+=Oza;90i;gRJy?t8etq{P9cN}vx>^+s2OPIbCed+ z1Qpfss`M+jc9Q8*3J!aQCcbH9`gdv`eCE9W&^&&7_^ii>_~`+qf?q0xma3IDn6tMM z)4|Z{s;1KNCxnNgH>>8xv^AJ14R7)3ctn(hPB+#0i;*c$6MFgbJR z0Zq)CisXJVg`{-W`;y*z$SOo0=|wQYdy-k1G7)UmZF~t#jh|Ry+IH_FO_`M+U{TQmf(>X$vpe|nViU~eu%`08In`RalC_RhoYFAQ#jZq4UHL>7HsK237D z_oC_mE_gnS+~!_|Pk_r!lCCHjvn>uZl5n-}lD%sJPTk@Y{JUvJwzjq|*`Nzp^T^FR zBRvizB~c4+DVQ&s%FoYmk8yWY_3C}76ztwgl>uPuHT?ljCXu87QFC*v$h^FK#f8AqC?mj zaIq_f(vD&jm~2MYMy3%gtsL79tezxCR=_Wp!KgFjBZGToySd*^>q%Q*56e?Zk=u+U zA{XJE(fe@6JQg{(d{;~2-9cwrs?~X#jlPO&{%*B_VpcH$#cb0`9+*5Zhx1AlvPDMh zwPRCkX!a{NP{Et3r==Iu#>#6TtW{y-C~?b7XczPAnp%7Ug7l_%xrZg^R8;wX$gzR!jZTh1uoP+#FVXzWQyb#foktdxGYoO z?~DRqM;)j^Q1Z|Wb8bEGC}?_#+^NwzQ(XR3_F-sGX|c8gorZP5gT4u~_4itquXKxQ zaTdTl0y}K6P&~q;@2?5s2q&o_k!!9lQ_f$VH_kjq$8<;S*0bQ#iqEUC$2AlHc`KzPjUnw$BsEgcep6g z%|MM>W;1Pr(lOr=eK)g_iFTnS^ z$%Br>oGN5@SH^Ry<|Uy3SlCrU$O@6kTaJBW&`W@MjxT^Two%XEsM|X-csj4mN~~uG zsm5B_!m#-_xMT)2S#DrxG^WL>g`BKB5@S6g?$U$XJbSZOc`x>c;~0$=9GKn^W*c81 z7?gZ6GmLTF;gwuW;RF?OBwagQkm5u0Zgg%~hMVpgM&dn&Nr{PjAjy}JT4&xtbQVKJ z{O-PR>vh;P=!RMDv{lf#`NaL+7n1y0pZV_`WEAw8uHm{64zp>-5lW=KHebn(b{dki z*?(bmGpLJ*KD2Vj+wE$frM@IuH)|;~^{k%h$n}dva4dU30(=4p@!a^01l1r2{jItk zH)M~~C?Bwy)T2>ovSrjUzv%44kdwQw04YGrphD~i^qdxYI@bE!Q;d|hderxKRxx>T zb%ob)q2K#3XvvNuMS>-#L5=nE3xKeewy11P%n6Cf^kvb;Z9A1GlUwaQq(&eHJ~~qt zmtY3OsPGj+2S8BVxNejeGeu*qI4dYyWzF}P8xshl>rutXhVkS6q39ubldjWK4|9ygtJC!?DW|4T!%r-$TOv9hK{hqz;AkZAeZ0 zN0OOw>uQ7b11{r@0hS+*jiv#@eC@tF%L9C%HQ#xIH@!fHFjBGf?P$3`R=uonb<^Rm zZE>)I88dkE^Wru^k?=nanm-&{j;q`a)9=|0sOE~S5XqbLeCZ=F7m!S|mn+@jzN(62 zJF8jcV5Y`pMdPN43u#BT+9L$dgxhbkFXf&Q| z39oBk{S*lJI7`n*VWV^Np~vC(M)Z!aYh=n%yw)%KjZdceReTFwNE(y-PXyXAo1o&tw zHL9>FTbO?x=}qWF7aBXqy@=XQn{B76W9V{iUeke*vy(ouK~dCM=Du^`xK%E%F9!`{R=#eZhog&>STdB?a>;e35H2*y&)a@gNL0iNZ2koRIf@?4JjZ95c_K$z{`c+iF z;C|6Cyr=N|`)B9Tjz4668jSP_M@F@5%2sEMBU{0B883sqC3=eVnueN+Km^!=B|L3y ze}%*k;14djlLQ1JWOaL#l+0KD88m2!Ji`0!NyV+KMgB$&d zN#D&56IIcwu=|DPtFYckAoW7!3rZR7M z%=;RG;J^){^6~ReZ}LYT$prz+`owr&f$8wVh_RSBNc+mKauSPyrQI(0(JYED z+*EwsR`g0PUq|KYCild2c~cvM3EzS>+` z-Fqb#b2bgNek3S9O=tDFPF~342x9mNnAX{#z5AgrE=N%vD`!2N zU)>Z}kyFelb=_L`L1si1CC>V-tHZ_S16BHjwP;?vHg2u_!S!m@R>SUyVm5KG8%k;! zjA;Sgcyo~6dr+PdAc*12Yc?X-{@f&nw=B=ZA|i43iU7g47>g*i9-VylFLKPWV?W$= zQRC@^kt@G0eGOL!;tblAhKOs0<+{VTId82&2W5H}VJI4qmVCZ^H+a{SC>pH8i zO3?{+)$cFI3}(pThQ@ayc@QQ75)IYQ$zP!zu-NvwP3{2?1=`1IQOsq5(vnQp&R7e* zC4iZ|)H4%J*CllR+$^;?Ua@0Mn~t;qapgC_XdmO(Rp1WZCDoYf zX08_e`0UYF&v%M+Vq1rFc@r(3y&Yxr@MJ1{79UGc+ms|)`prj?!gQJ_6~utmtMHVs zDK(Hb8~?%&$5LR2nr1GUE4nwzKHhh+FXq(Dh0c!n#}Whv))5jeDElBtp~lMs`8)BSWHr}nRJsT{FpoBmNHZD#V_N4(09RXT zQrUiHdmR~G;M9=^zO| z1O?8zR};aR-vwT+^2kcYo_m{z7UI!EY2rkUR}U(U ztAtLx4PM+Bmw;GYvkNa^=ma>X-Av+0E^P%C+Emc*V*Q0-nP-9IN~U0W3DP1!94l^} zRPA9d*Nd)+S>6q{p~_x403QM>0>eZ6Os%A))~PoP{lItmMD2FbBSme{{rMUz z03~sggV&vu~66Yeb@`9_xn=uRmhnTpEPOQ~QGgq`c7!Srqt zs5P{;1zDBR?$Q_Q7CHlK92Ep>4wiv@mQ_tu5*x(4FzOqor{z>=R#`^X7iHwu>_Zxe zM|B%{Y*iw~r(8eb^*>Gg?==3u$4j)%r^Hx7wPyPhwwzB4D*oQ{;IHvqSZ8B;m)PR^ z(4!yB)Sd+1%QBJa=F?h-;&b+skTPJ)o|)dSiyK|uV$K;Y&N;&Ly#5g}{W4(7X2{!z z*6v@)il&5?UPNCSYzWkq4@ArLYY5H-dWJ2`V}ff<>cIf3k1*w zFh~%ORU~gV(zcSu16#JJv6D_M_KLx7S3?40Q;%bi)&>%=gNv%%RBn$!@(_)Gb&-}C zxNcG6MHsa~4=Z_%rey`ySUM6bEO4;_be&TPO0SxgPm2yOg!-wjdKTqI-t!L%XmFdZ zj;ck?E5}Vwz^Vl$R~U{5Ss2uMBP%LHGe3zLd#W2ohJ^*RP!BLGg%5&R#xdr`WH<4B zj$1QDmm{%oX4}vrJhk36Aci+u8k-$je3tY%o8ZgurGJWcq@zk#2mYWs--%8EUt@>$ zDQMprd%t5>TBs3HP`QYF%{hJ{!z*yrl!gzk(0!pDk`i>#rem%$zEzchRA1o&d( zWh8FoQmISylCDDh{ETIHqjgWe1dR;A^rs>s$xxrr3{G>MyGf8%nhL^TN=&puIWpC* zdY2#>;mF$XD4vNtQV6qJ+uDtaD{RAuoKW3T&Rs||V`@N{G?{BN_(flm5}&FnQ?^00 zt82fD5{WE#{MW4RV0j9*m_@y6(8q8{+ZqCS7zO4z%IbXMn6;XF)1A6;|B-l{>AWF$ z(yqkFvd@JaQ9q!e9lE#cZ5Bb{K5Nfo>v|IQUERl{dA&&Vy`9D0pbFYzBwfVN-e6*3 zd{oIjAbxYRa2j8wHVvXhaJ*=RQ44?mtN;H->)&HcbvdVQ z9{j1-vkU4@OCdKqWc>|F-swkq#+!dS|AY{D*2xjJSpV>0_O^zwXMg6qq_4x{q z0YHGX3<%ud)+zPJr~mvdXxPnMI1U_L7x2913aCY_WD1O)o6t6aHJ0umsBsE7S&q0~ zEFmsGJSn3sJAdrzgn{|i_}O7GQ88-G@qR1!?x5&!n{nT~q@D?z1v#`ux)<69eyLu! zUz+B;x^!=&W%9wNu09?mq;H2we?45|-J&{TjvY$!2;af=2UllbL{e0J)Q0ssfyRQs;f5_?!f=50)<>K6uVUu=8wx~{)U=wu%G3IlJ~7O6zm)3xRSy;#t82?)p%8tHcH=M=M-NirX)%+gqDs9z*| zM$=6dOHo^`W<_$Fq+y=>!+;vfQtOpQF0##&3|U?^ifCdHBD8AA3f=x2G_b8{Th2|K zTnL&QtEFvA6Atkj0Wiblj{u^N2wLb~-@vBQ9+nE-ioB9=TxX`+ltCteGVS_YV4g(SkY3>&6|nPd8Me{jaw{rP26QW`!e78Iw~O7d%?n9D=VX^CUCLm zbxgFEnfG>*p}N4$Sa9K%!t7%8;fzNAOR#>OO=j;pj_O9)1(2vEa*s=HX)k zpa8|*JwX5WR&)U<4nYDVgTBa(TS@W+w~L+fdr8TNZqnHsa1*YCm&e_z3aWS`W^K-y)LO4w?eN7 z@qhOs0f_3a-yu@m1Zs?6lI0%0@efD*!gTsZ`!P!O^BoA+okAvclZ01OGpK3tP&oO| z$tRM>Gpg(LR;6p!TQi_f%COIDoody(UakAloY@yh+Zh48MW39TVjV)-_R~=*=&jwY zgHZxr+Bd)a!?Ed}*8~ z42<=NjK7b<+|WResjT9+Yuz3m*TBaJhn4pyoXygAivuJDMG*T|_<&#CH&yqC zRc`J>!dJ(G&fnJ4|My_||GzCve{=+@tlmA^|8VU0{3}cNEJ4q|e+liszpPM88VT?9 zk}-NY7nE~dY3sYXVKco=kaY6JQt#Ce=A3bfR3NV9Z=y+|YSeGY<&)>?XTTST%az(@ z?oCTBw5s`xsY|i9E=6uFu?y~*%kr}1d!_Qu*wGzI~`T56x+>ZMvdfnWNU{7kA zCO%TkmqYJZ-G62!{ll*(-Tm4fu{lP@b&vfNiWcMnxu9~DXpeF{!U*QT1Q^i(pFAHu z#3$i}jNI`42wv3efhN;QsA>qkxPWX|-`jKg_bf|Tpk(PZ$)GmFi z#(0y7;6~g38q7U0H+c#AEH)=EXrC?0+&pl+X36b=NjvGTXxCWAXNX=PCz<5s7qVj!{S zAJ2BOQ_Hx(Y+&e~GNa>4qX7mo`sBF_d$8 zbFWZTuX>w)`-o;+P~A^f7FHs?dYh)J{T>%-!MJ^?i<{ov4+S4-@U{ zJ1Efw;_QWBjD(na;ara|UcrGm+E(F5uaocwqVQ1i2pZqwqS1Rtg%&xWg75Brj;1K{H9l9rF zu-p)g;SD;pp8LObF(VFoG9Rdc_aB9qy1u_x-9@y#ysGS3Snb(HQx{sLMMND!7w`5>m>!$yAx3r+Hd>tOVVpf`?opzLC9)* zrjDla3fO4DK)^&(=m%<4Lh-J_u_X$PLki;Itfq>|0Acmw3}xVun{4JDoYtU!Z@vfX zP%%d2U(k2RORM2dlm64$$L}4W5s;h^lYpMZO1nwMk=-MPVis)mjfk3Js z8QwcFy{+Y_25cus1A&A*ZgEoQv>!_53Lw~x*K61LMzzrIbHWm${$cUQU;a2O>X+@7 zO74*BJMz)?+ueJfl#Kf*A>xF+LzdsHU zA3qs7Gh~+#O1o)gpY%58!?D5|zc*~dW@&k4tNFQ*LW_nw@}@hkV$i(q5bJh@vfyBs z#pl{L9&Q}E-=A3?iJtH1&ODO5Wm55iPfap8U~Y~H+xaL2A5~kS)jSLzw@QhgN^Kk` zbl5qv+xKLL1oPh~n|MCk(!EjI^qJ}Ux{qGQQ;qCHn(gj51vKtrG-6(r7~lB%yI0I$ zGxd6TjmI!+u=AXu;cEFcPprHJ2YAqdr=QKoH}CC3G>j&sNtll*q>0ONiCuQ2BoZFV z=5qiRT2P5}uZyIwfmbAV+KIxgVt(Ka6~Z%98o{q=)?SowuPOo0eg`N_7&BfBR4*|zJy z5`JhV#Eec}%o;JJ8E$jmBu7LX2)4}BO&((I?~R6NqFI?=J85*h0|>UjY7MLmra4b{ zTDq5C?#bC(G5y#Uptu=yYvCb?cFkn@Dx>QBtybs%OP7oL$LX#;c$JFh`6aGZ!)CfA6E1W&fM9f4KIz)Tp?6yC1WNx%N2X zPVl6Bv-9|-FgSmxzFgCz;CJ&{EB;Altx@`wxp?~^<1)NolX!O!TD&mX_ZoD4X#0m8(c8!c@nz~7drL=qyXM0&zaBS935UZXtF>uHoZ@V&;?DJPeo;{ox`~LCiHPiL z0E@}@-P=08@2FHYwbqWGfBei93B{({ZBGt0Y;14OMi9n~BUAl`7ALFv3Of4QFpjcE z0-^?|7beo|xF~JVxvD;~nHPJp4bHjT0*tvjCvJCPZ6<9AU6t19q|3U()16liY;`-X z5>mQ7;=rU}gpzwd!ZV7EFgY5Nun04aZTirogYuZp@cMp4=L z&DdO>yU%hlHf0_jyplf>(>TJQ+`}8qeikXVe)^f2Cj-7&>0NBEHrxX5<$&Q3MV=j9 zWS;@Om;@5Q%C^knwDxh@Y{U|}I9t!Ij%{KXtun?sMm{+u>D%u@(!t|Z^`XfIK92hX zn^8xVHLtcK7Z_Yko4lxmm1e}Y@0RXNQqpd)cX8YH%pyNuaszA4qFUF*^VJK#yPu8X zzux>mzPGyH!TqB3Rl-bfl5gYh)4ihZ;Tn$}E{lsqYe1E5+u)>DFl{^_ODSylFPo6r zBNw!8>9m9mpmJv5gw(as+g747@xGpZ^`_;?hIVZzKb(Sdax%Ice#^6rPD`;HA_BW; zReg6LbZ1qgk|t}etq=`?MfaIQ62 z(90_-%9W@N)^3w(16#G6iS=Z#QYu zrcGhNM;-#G(T(4xcfUE6$6Kk5H<5N}acM}mRwsNvrDyVR2{h2~O`RJxuG4pKc&H67 z3F+gq=N4VR?GqEtBc@kQ?c;nX%fy3FOpbX7X?<{bJ9VZN&i{QkMQr}T-yI0j{2|^e z>gXqU_tm0kPL^kced%TYt=sKUXk6vwZo~UJtxfH5jjG8vi7_HB$`wxNXZJn+L2w2H z>}qz??7Imc!(Qd>6<{>Ls9ty76sU6p(cAqBj05}*|h%hUo`aZQkhY<*xCM45!V3PVno9In_Z^U2(MuP!}Jks23 zst1uD$<1w8F1ZY@w#Y{W_`r#Yj2{-Qo_xNXAHPI93?0Uwq!efR<#_pZvzHmk*{hBU zFv+8VHrEm6RjNeH=v`alO-gt7ZJO-!pq$&xV>RY6B_EKk=MOjB=>R~#~ zA6Lz_Rd#p}siFWWx@-ZV)km;r*i0ZmnDkjAuj6rxe&XX~CM>J}%LhosobsfEt)dDLvm{}`k4k~6^T&ph6U$qAf z1h3YH6ijWb=Vqn3aTp~0ZP7KTUnZplKpa}WP8u6@IyBwWyTXdDP3W20mhkqyAH$v z?z;{%;aY=sFbu1KLQV+?$1|%q)tUQnt+ivEBd%Rfj~lDjhdP-6pK)0Ch;B*6!q64- zq`G!j`_G9?{~Fi-YwQ2`!go@1>!R@I!#we5#NyiXFdq?ImxeTd{rp9?TRwg1ZH6Jr z@?5I?m063jU%g4I#=WQWrL|m@Ee2EEI*EEVR@XHgV7V9eAzF;^yrr5we2Hv0$y-Tu zU>Hz%6`Dr!JG$5<*dT>xHtzt)+@!_USkYl`>1bCarvTBe%F(JpPx?=H!(yGN0mwaz z;`XSm=_y5M$S-`jg#(Q95#I=zTi5&2rA2x^=%bcq4pQ9l8MtlUU=^;)kzN>z9g5tu z3n$YzwtVDxfx}DD>J!oF2`Y&rGf7;{J;a1H03sh4S*q9=zQBsEW7bvU!&0P(E{Z}e z9tXPF=*DlMepR!ElOAYvsQ=@LP@q(KL4~GRGcpIDB$;QkHHa1gj(g^o)U$gPBa7RS z(8A-lX1gPq_kT-0eE^tPsPrj)^M=h6`dBRBUgl z@FmXrlb}7x_-GsRPImw`Su5AAqXyF&UaWvJJUASe1G`KfXeI`qNr4&bc3OtSHR_*u zemGy4Um)VD#^8=W+J(^gTD-&7i zhstrXPBPPb&SBb2T+rHc#sYGjn+EfA|C@Jku)`- zlCYMl6v|KnUA;?4zSE}Kfv97`w<6EvE>Ez`5Xg2hhmAYG}Qo^5X>snaYSby0F)66hYkbP7OOZUj&S)XdksGv;V z3$C+)i!d@tm)gQX9OBoJ<=vwWC6?dTG1SCQhI{cX%P3n3b(Bwhb z(!8wPvWOo;3bw%=O(bI?9Cm|MzAPv}qtK^rnf_2-R_@_ZUY=U{dL}ig`>}`U7~U`3 z&~WU#i7-6W0T9LzF9CEhOcE2L7<3X_li0`b`G~Gp`zXHI*VhsJ_Z;76-uW*zzdO%} zGheDr49l+x)^KxEFGh@x)#u+_FZuFe_gt+_Sr`QR%i5G|4fR5EQ8=BK)#n+!iU-+bB zAAa?>&xifRbG}};ecPeHGWJcAs_VpS%&PpCg9X;|cU&*;n3Rf&dqCPRSvZPujz6h? zUh8TmdCAD~D^&2{$@wz~zo&<@v0|j%VCrB>G$m>mE{Hwcj|c}8tS#@(DIP-38o$NH z>S^t+d9Jtba(4sPx)6OK=7r%)3~xC%6!x%ifA9|gSn8Qax)bJ*V;_x_&y1xahGttgk~Mv{G9845Jycv~6_p zPIO!rsAlb)*ZUWhc|))TZj=(&Q7)!*(i@$ZU(E9$+8t#tkB5bepC$eH`?2qN*rUX4 zN)-eLnegl32|uSBmxn)b5x#UmUsC@X?_v15f@k2s#`7Y+*Qq%U?~_d*qNU56JR^UD$M&8i?lv~M>@Y#I9BO>Sc-xUu z%W&?v_lrsOEuj+e>qb9CmXfrzMu%Cca5!pyiYB?0}xw5me$b{>= z&7#jgmuiwi^T3DfnV5UywRJ#c~IF9@IA=dV(qtX8MU>iT?lNWPgXV3nOOgEAOgfIxsGxMWO zDdfx0J>50e-K^1xPWI{F)=)K&01~8ftLBg>x-rr4wm(MH8$NC6Ox=)e!Snm zr6auE2B0r4#U;dt=Ov{HUki{RrF6Qn!#r`J0m7FVbtv6<-SJ(Bh!x#Rem z*tp}Mouyr@4u_WEL1cP({-RBB_{{wOR@1P(C8+0GZQA~CjfSI5ThHcPx~&BgTm6^D zTSlXF{Zp|nJDc+1@IrUk9RC#7y4d7ze_j4R*SP*SP!j)HGV)}4$4|ff{y&@ZRq6u* zz+5O|D2#knt1XjJtln_Pua(ooeyZWSe96+RZD1rt>`v1XN4-wb2Dd^$0CIsw^AbN# ziNULtuk$o(<3Q5yh#!t6r4cQU8VMHM@hEcqpL6H^COUih%!Pf}1*dknj!Nspy0H{Z zI>}v=Z5B3@$dn@GGc~rBPL%ZnV2=6s8s{&j?{3vMDtL$8n6@3mO>BjfddTmRJF{O? zR37PiWWK?r+HnE&=^R?6cTbackB8r>g&a8G_0t6znrP}8Lm_aSO^&FHax318D-42{ zjKmxm@4SeqLZ^$u)hrfpb*;$ILYr1&-cF>;-~ODm8AWF3xtZ0S##%U|Qk4a2;HN~6 z-)yHkE4UGFtJUK|f&tcB;(~udH;^6senuxPr0j)%&NimU6!VerOj!mUYM}?r(n2JU z&$V4zx*m^xR?Wid&GxA71#qlr`-ZwOmGm0Wx{CHht7o27^tnMvoCmC>L6c;DaUts#=gh&Bkic_;@3(Enma za$PeR6^)RD##p89w)w)}4Bu~Mwju^tem#!t-O@;a^cxD78L@nwSolK&^p*!u7?sa~%_m+W1(K5PQb(Jyl;*ia z#-?sxAMm~gqVTPKhi=whKmK#d0B^aF%D|_gW>}n%mR^sjWA?4Cn3gZe_p4g^(qK8- zmmX%w=qXQk=-!^!;9EA-+t2rI9S!AHYhmRB{2Mxw@>uVHfS>?YdaffOXfDtY z2*~vurk$`v%fWmA6105)Q1_9l)e7IeB8Wi`O%menF#qfiUJ@ofJ5=&H6kcqz_qi8d zRXjaHPI-%On&hh+yfdn41S>I2E*{r#`Ld~U#yA8ZLZd)5l+sR&;t@xTOU~o<72_j0 z%#O2ijay8u=(MbuoDGhGMF^w=HfqADr}$Yxd4L>i-n?v`YSePCXrHlZQr?dZ<(dwk zh`OIV@cqLIblP@HmD6tqPxS(CDO%U>Mu2{NCcTKiaA3b6GPYZdyA-&%Y1^OvzIuLo za-ulxmtgY6`O_bcd3QHTI+KCwS_|v3Fq5@m+1MbyNvd`QdJmCRXEm-N4k;$rVkGE; z0S9oGopPVu4GY*pz=Ch_!)D)|NZ&Xst3O^>L&d8KGR+peJ;LG*j%TB9|m@h<;j)&h~&Xtf<-taX-gBE_wl1p#0YL z!(V-W`Q(ro7rpw`UJUHewJoT~jpe%Pe*L?_LW_c?`?HODq+(!8 zN#Dj42RJ4r?RP$T`SgsOrQ+{1k>{@5?OeI7P}B=<&XISBYKjP%cx|n%ZBKJ)CNS;| z`-VoJQBARke^y7CD|fH!7$g%$dl#q0048sM;R4++*r(s1PzJlh0O{_gm4zd|TKZfo z_Y0JUfxSA*IH>8`q-Af-ZcI|`+Pf-Trq77Qi(wg%jIOm8+6yK&ixSixm#Q6?DvINq zE;9IS@o~!r~y24zkB&f^0 zG;ULX>8`a}qFjDhy*B{xQpr}K8jy%ogK)D#nx-7fFR#X~?aK6Kry-41Px8dP8Pzn+ z4KHxZi^0OeiX9@oe2ze5%yj0n(ygTq-#ii$B=bhUYd8F1sr4(42;Kw};xc1# zlNGsyiQlVO1YPI#S-=@!zMv*&xWIOVSzCgl2~>|#tuqA};Gdbc<^ET8GcD~qLj&5_x!2P11L!-s5MCRe6h8iesvLpW0tYHr;m zzK1t|9SgQ9i%i^OAniK(p^5v?(5jT{R>y`0suTTS56?t15Detja9tY#idu&l4h|t= zuJPp7YEjsoiqOZ(M9AC8`m^&M}LT!S=(S5E<_;rvEt(EkT|9A+^K!`jaG)R~q`SN`4@& zPgCO4Z`moB0tr}>yS_CaLqtu}zxi=vPtGP1fC|FQ8FWk$BO)JD)4s8C_tVq%Zykr# zst&H@TIrDHoCe>OMY^esqaj$b;L7SK4UyMm67Tr2(N`v)KU z`S&DXLX6rg)C)JfJNK2pTF5c=eE#uL$4;HznLe67&mru6n}NoS{p4-*<6q~K{$ptE zud|;Yba;5is5{xtg%crv8ibt`EhjY5EW|;2e5%^|H?i4}S3m?D{3bD8uPJDX0-J5M z%Lc%ZTXg9KAaN~xb*lfP=s*>0mdJ(xTYTbRBHkk^ACq;3TLp(nNGG;8Tv(hQzlnA$ znambuhg=HC5wP1IvLOxi+s)$+-ZWD>w8LX)tU^R`eeT+WdEm62lG5sSM$e%ILM zy#(z?N2T?4wAaaR0Su!DfYH&sD80KDuc;Qx3&cT-0a1|5kK9o^>8YAH zC3orfTWKfXwJJPVl(zU|n0ox;R!s!(B`CnwW$b*cAi3?aITifJzkK%v*GVZtVe(b- zkT==hrIvg}_-yl-*@eszEA^D_^c!bP7ur_AhK7FfxP2iCY7Y*%(*PSM8XE5aHBf+} zc0O}w92@R^luRWjd(^;T5O)&ZqmMxaLJc*8zD^&GS?Krl^YqftFdmhXTKBV%Cxr+9yu~K&A;xkDV1fQF&UK&yeV9vy`iEnHww?jd z!z5Ngi4Q<_hUy5n7yjyzY6+J(;=Mw*bws$1_N&fBy~nP%THYdfScH~Z5)q;g`KWq7 z4<>r7smPR;`xH0|(IL1b0jiZ;XVD;{k=_0}F)&uVQ(a8quW}wKV$t@a%K*ccco?9j zqO~5V(H*%{8>Vw;u{n=%vhq#KRuHwzK7!cQEjO;j$E+&;%Y*+$%MZg2d~s#{9HExn zY?^VABth|QeM2wNKsW{Z+1x$Ryk*wvq+af@5 zzaBp@cis!x*$*TH>{p_NIhbRvzvQ z#)xil)L>D&1kF6AyJphZl7!u?tIM3C!CNA4NmjEFS?FdRna>JrE4kt(d0c0>f$B&G zmsVXIXkPu>XKpxYHIN@u%orb$Yn~O-@qvaHnRWN%OkOGHCcma3@YwO$j8byk_a@z6 z9-XPRosI}}opn{Ag!lOJ^mBQ=T^!#J$4*N^JC@ZTNW9uuO;iV?LM6Dv?iBE;$(nR0 zhR$HtHx9rRTU~B)1L@-9C$_l5vWZ(`fgV@Sc#(wF>uMs*ccxz9)@@P2O^}9l*xj^d zts7?7jk7{=*c`fhtG0idivp}6=L3Qw7H|T%&C+R<} z7W+bcn}Z9uxcG8#Bfe}-^{3EESPnJOx&-X9ES5T(Bp?dDt`Vc>I4K68@D0H?9?T$n zUtT}1jJJcM;?C&+cVz#6@b=zuO=Vl(IQFq$1Vm{n2uK%c(k=8BfrJ2|C{=2tOLtV1 zVqoafl@>@S(h^AsjMBT507(c)uK|J3i@$?9^US@^dq2NBcjkT1AE$)F-fQo(&pvCf z_5H2|?N(0SmE5y;m?+YnJmcKi^`>VrQu+KhGSg0fhQy^08iZXx(>*V7nm`}I&2-1( zWI~n(eKbfP2L#w~r#fYNI&dJ~Q(s5dJlmQ3+=JnB3w|jURnPTs@4?#7^&6c=!c1%C z!h5EjLl)BHz)8KH^7Rd;9&@CV7Y*M7fPAA8H$AeHP(0>Ek-NS^>o;jkRsIDMMD|8_ z)YTzMBSdj%S8!C0$yxTFxS&_cnQ{nrvvPlx0?eUg;_^+khy?-W2F&QWEc5f`kZpqMbGRqJrYlZ9Y!H(kt3VftR za09FUz7>y)5%)@!WA(eTYdy-#AIB)9=sxzdYgg zF-x|TE~e)f40v(Pct-Zl<)l@kc_A@s)X|@nIa)!V_eA{{bp16NX3e1nr6cn2zx zH>h$FEuT4J9;iIXA}P!Af{d!Zk)spLN40f?4@nnD{)Fdto?741#K;$(92PJ5Cf%P8 zS#{*dwp*~rvGx9)=glC9^P93C1RWK`)~QoZ{#}!oO!l%q<4h2J6I(CiNJ|{vKcmV9 z(YzX69cn;6`HR#Qt#Q>c4qeYEx)THxWnL#~CIfQbDj?Q}E4s)BXRD{cCQKI{=r6C- z-h?ua$>AKzP5q}j;VjwkIm}uHa{+v44d8^>F}wA4R%CAaZr){@!SqYZJ5!fh^Pv}B z&u$JBjuv4k*{YFAG85(TTvx-Xi628IQvsJbsSH51gV(*57K_=3tas!OIA$B60 zz|z81=Q$uJrQpv`XeI}>M|wA!3^$mSl#kPg-fuZE)ilPS9Bal|2T@Cwzl^V^1`Ninqp+(Bgj)?f!uoXh$2 z*Vlp6m68awmXUx~<8ogKg>$!dbZ(AwV-tHoWij?w? zE{ZPM=plI9T(9VW%i4KxBUpV1`GZ?@Q%)dWJM?G@OX&nQyiaB|bSO~Bc$iQqZoK;1 zZ3h(oW#M#IH5!(edy09*siSMuKDT6Y{dL$(4tGCrzwKk{jcwj}jAvHMR{Z<=U#N^$ z35j|@nq-&5^1i99g&z8s3~E%*%h^Us&)3Myn^W8X5E+N@T6=wAe^Ac_2j#=TDUTO} zXL5;%8kSKD_sOpeF67i*Q`bWvuc#_LB(G01JZ_{>zTxJ|lFe*6ke(UHXCfA5-N&KV z4sUde5Gm$-M@|}n376kf)zt=ZZGQp$Y6Xt2C_-$1CFYUC7Y8@!c@D2!x&63K6`}ia zogOOcp$!W=1GZjaT9a1@#s0dB4x8u%pT0p|+7@%^MCjYG#l1 zu0)ee$1TC&Lt0z~l3`n{y?W@Gl!v=D#hhM{w|ufq^?h3SJNcE zE!;lxOQyp21yFKzC&J<7UBA4Zf~ONgqm4HzIU{Y)s%Np0wOf-;8MYLGL1)qn1yGhd z7y4bdS<2zZUyRzZ{JJmk|79!k@11h$K%wF-YdLl8g=>A5H@0#YRijD<4W#kiewB=@ zwe|zU0RH}|8?{-SJ=5M+b(Xk*H$$Qm4K0#{CC~)&Q(ejtHrboB+w9PVz-XrSb6LcI z4);n3bZnGE?B$ZVcR=S1atti_`ARgwvc%7L2dX`Mz;o@QQ(QLmE=x`yvbx3=*woPgxm3y4@YQOehE)K40W$*V?*JWiXVfxG?cVSGsuZrJg%2^8 zI&wrr)y2#CRd{&#c{xqH1ocOe*RrgHQr7|C5J2Vdzv9@}5AaWbEF1fro+ZXhvW9$G zRyoD~st(3UNl9dGZkcaXA7D9EF5;65x3$Z0l%u#49_8hC&x^v(JY2$LS^m;jSET;P zQ*TJ#Pc|iY^{35bLPARQWb4GD-Qe9&&&g3HITwZX>D}Eidinr13by!gkCt6oLs36I zVzHw8QHZS_4Ch*@a&YVH5MhTY^O6H<3~Iw*C1Su&$_PX6r0A&*?yKX~pCEy$(nR#J@b&$Zil#mYE5iU2&Phi*RIx{N96q;e>6=-@#MA zJTdUb?7@DJ{>S-7YuSLXq4Vu}F;LU16yl|;PA2T}P+N^Gz1AAxI3uvi5B8VqvH8te zy~MnQbT`yoh?8yase?C#O`qw^7-^2@XNMHz;FJ@S45|-1x6s~i>?ycFzQlcaNQOS2 zxN;c~_rRZz#BxoH60!YSxw>YYPsG1?G9YTz36Yz6{-k` zco370mBW<;_GPrJeNq{xLGN|!!PlI9x)&yvb30x?*Fm|DxxF`^n=MMzYKaK>h*Q@# zF%gPi)>!xPNS#;}%^G7kdb5LGe75%j=Q6djWYCnFzxc?7(@@?yJrLt>xL(SWvgYj7 zA>UHP{@M))%v6tY!P_Eh6KcdFR_cOJZ=sjT{`i+d9{u9(k;dESvjP=5>!0zhe+b&$ z5nG5jH1{Jh<-wwR<$*lF5Y4WTwXSDUFWuKNf8YJc#IR%Z%@9~kaQH6N;iZkIV z6;HFaDLiX<%xYl@rO9b5E{ZqSn{Ez^Dy`*G*UP;Oc-pgSdjsCmU+C%m(?2anjEiuyeo@T zRaFV8-!IQi#gZVW~+uqz6cWj-Ea zK5QFv)dMEcLY8@6`)K>fR(sq)0ZB>TJ*Ucg^R$SfS0wFFWv!tmgvlP67dCuelRbHS zN9%z(Er6#Z# zV6~U!{{OJr{}X?0tuF>Ug7Zl-6&J>7p{>O{3-hz9mw=?NM!r{!XK!wj=#0M3lj|#P zDpY$L*H%d>I#f>1DFjoRT>Z2H5fg)9#Te%xX7H9AuOLpz`BWC>=hg4_yX^PvLaWiL zXn&5eZ4k)fReJGS3NO}EHNPO5^7a1k6=5i&AWZ^F_57O=fEj*AS2}K54 z&Ysx9D2mj&%1riDOH&t%Ku7!Gnm(hmvzyZ4id`Jzc5^~qMPCM1bt5gGKN1ycl<+5T z9j~T%!5ZY?J3bjN6zzDH^m=;E%~jR5n*n@{q4iKlbkyVY@E~E5_ue9NfYG8jlWT85 zn->{h+>>i*I~nUB2rEUHnChB!@;DptGA{*B?jD{_O^u_27L5vhY+_1oRx)zLE#0J6 z5$4BUJnDEwrdF6n0>QEd4T2M5w{?*#HZ(;fwa>y9(6*feJP@lh8?IZNmmbgVb2eHn z^$Mc5MaGs#7dc1Wht7vF>)&R6beEm`#rZ6&usnp5X)meJ$*`20f4~_)J(CqA$J@wu zc0Nf#&))#u@^@@U^QwD?GA?E*szYtpv?OzDrQViV&=9UWS8$I*6I*QdWQWLv*izm* zQt~o3t(x=MXcgSIdXJR)%PYPqqkm;ESI;6>z!WVah6Gv1Bf3`-%p6gfy2AhodI~n~ zj-IqOEkaOQ*?gjlbI`ahk@Rb#%rd5I+G$0l31hDB)td91KKt9gc$f{pHW98SSg{|} zLr}Ek1#iZEprU>!ihXKNzdh~>l6e*6xj{tDJjNMH?Sbe7uw)#XhcPI{VE6{|>U{s& z{KO4?*tIV|5M+PBR>~6Jx88S@fA>sAdWR`XTwo8vs)LRx;cIa1+!XIr@3&rA6k-0# z0Kb-q=cuU(15omM+ukA*C%L;Lk=M;twft>6?5upjsTUG(NaW9kJovyy1H2RkUn;(1 zIc%fu7xxH8p-+~)t+R>sGFckP3`?&7VoX(m zvI*?9H?gP3Otoe`<&y0`z|Utd0LL%UN1_*yKrJ6j$LUJHJo0E}3Cbn7QD~jZvu9Bwo4%qrF;(bY1FKt=>2)j{miF&h zBTTvg>`N2+riyncjqxA!#_r8O48p&5df+&2ZwA28lt<}Rswq2UY89;i19&qWwo}e& zD#Vw&RoY=2F&*2OBQa@=oY?RZMg1YRD^h7W=XyGfv!7~SPL`>a6g6sPiZ-3B1eSG^ z#hzdbYTK;xlW$_3JU87#zLFm(s;mBT_@aIu+l@`148~-2e`~;7=9MESjN~iN5q=&!VbYBbp_V;@DvdyD`>@C-K)x%Ftwmk=*QY=>*02 zLElVa5ZLncqTZxzSO}@^$)OHglB@jBW32O?qPQO8rBtf~N6G}*W#^_q{y=f`EJD?N zO|Kn@^?;YkL*+ejfD_NWH(F&a!aYMnz(XUN(U2_hZFt}e%~Kx}NnuW@9G3sA)~JPv?24|0L|zx2FBYnQAwz+ypy^4 zgN#YE1JMvC$GfGGo;n7VSc)ULkQB~*7Z;HE&{?MjcbandeEO!&f{g6wx{z|lvzXkn zNth6n7KWO^fGjSZ1;1VnGx)HtpnTgDstsR^`Q{vJuH;3fPw1r-oOO2*)&o=GZeZ=j zgQ*r@8MqqR>mMth8Z!;{DEM$uU}nY<)R7PsUbY1aHXmvKA_^==E704ZGep?wuMCpv zel}4f&DwBSD37j#LNP31&{;(jcmcKm|egE8syZR9w0R zy@U-fTWljC<1s!lY;R^5PM;tG>Dhc2F9kl{GxOL`M)M6>Ice7}PMvi&JNvWO%!W6R z02t2R7hGnAT^WxegMw=#f|h0r5p2M*ogUvMOOKU(P0NC zboNRUzH&j0|3cRIc=%1qgpALz&kABsKCk;Ji0iJ+VpEg&6yd&$N_O4|H2aQJsBhHk zN_6Ck9(ve~Q)iqK6s}(Tk{Oh%;6_$Z(M9@G9;T3cs3{$`{ZD>8xWC~5r0p%EY0vnQ zc?wG%)g*3Bdrq0y<`p5G-I_=4S;}aNmg@z3OYwUUmYJ#YN=D+T_Xk@wshW@_&+nCU zrJQZQK~t*fvNaaf4XC@J?IY%14MW*wqYzv}Vor8HxBIZlw2Tki^V_Q4IgOSQoNZN&&1iqKi7rQZF=edfW$fM!ZdATSD9ke}k>d4&SL~)- zaPxT4Xo?|jSF5Qq=-lIGwJGPcHOrGV0~sgioLbeh=we-`*^*)IaYOwFWDi~W3G585 z&{oTbCMM?~8h=jK5~iSmAhisPs&iN0wB61X!@+G=PGYS-85jwu{7LxwtxADLN1X1R?TYiCypG9wH7~)ox{guIu zU00L)E5jl8ubJBEpH^nvfb{Z+ zXFO>1HZxFq%~ZyDW2{)27>X->y68=jBY$A>>Ik=#zU9gBD9=e? z`aC9aUI(pEsdsaVd4;_318bfYv(99!*6{So^efARwgpe~8Y<6Z*@@c=!PC z1Drl_Pd3KCFy-FJv-1RvLK~l4!JQQOc<&)qKXiUI=g^b{5kk|ew>wY0@h0yn>H^Ba zE<88cJL^pzqG?UBXd%)mg`^+UE0{R{y+sG}ajp5L2+MF@^X?a2s_g!YnB`8H)gaQ$ zZt%I)F9n%D|G*S7$XCHRswS|luCn*vCX9IFnxeZ6u{2AlVjx>X?t(`esZbR%|HSM} z_;le*4QHjpT%3)3@1>M1YS7-E5p$n!*LdF|(sg%QCw&5=1tf4w>=F|5Why!8Z^w05<<+SJ|=JD{OKgQpA~{ zEh-aD6`?~<@~W*EV&qT_wLCMgCpMF$<2#0U;ruS`Twx{WUdR6$XZ{_zc|^_2X_fj* zurxNv?&H#k<}yO%&G#l9a3Y9Jqb1kb>>xooAX2(6li4Jp+K)}fH#1jnu56gBsmL0b z1zvWoNV2#h_&-r5{<%Z``>RW-CF+vycO{(@1oUCTdMX}f{d_I`QvQP1*z)`}{e*pV zedkS|J=4eUz3}2ffnr9S%s)1I`zd9@BvOmKmz1Qd{h*>P1y`Q0md~wQ5}#%VP?wXPRB`^g&N?2DPt`q^iiddO3n>u^*Ro>m`DXj2s9pN4 zPlupU$KTz#wO_=4;DkM5>qP(<)l2{K&=`*1?zSv6m)Lnz78LzFOh=3(^Yea*4FCRV z#O#VXJas(!rrx8n8war6zs!lUSD-nF3e{sde)54`9qJn6Bz+iLh4=V#oi!bix*sKe zEB0^N9jbFwN*iS>dv0Uun{IlgdNfJpB*+`9Xf~uvJExd+|EVm+)Izv95%wd0w&T_|kmlkEDm?*#&BFYh<6B>h+nLY;k z3Z?%dt+c?Jz^n_eclzwmFJPTlmDY*IVrv6tfI?WFsAYGrcSC1&>~OgodXK$hI6Oam z?#^P1@V6rV1IxXTP~jpFU@q({!(HT5Swe{I$&=r)%{R`(>^jb5OdLs}zq+dR;PC|O zcc}y=(3VB>&o(RYE7Gh{CqQwIKi1_>L>6-jc;5%bn#>||*8Pi2(H_O_>+YpCWQ5Fy z47DqY^0~;T9-Li#oa4@|?`8d+`%^;2$w!dp>NC_HJt^*PGR4bOPFs~M=?FDNM~64L zN^hn{jI>|k-4L=Mdb&$>RkoXi4LBa@Me1Gr%Ag~cz+@ z7}57fBeQ?rhSw9%VfgUy`qoEcnJ*$wda-a;C!xrW7qVWY)mU>|iRT0CG4WERH@`La z?>t^lsP^2=rD{0r)`Fx2TRA^I_4G_|s%0!Jt}t>NWAUnft8XN0vZOa3jc*jPWKSik z%uDgjreqg_X6{OxIY}d3D4dn9JL<~W;Wn7Tk=4=2XeB$8@-^{cE zlUTJc|C87Uurg(_`2$<8J_)Ic?9Er;GICvBbfuO$bep#1HgffC*Wrsp$I)SUCG}mw z(5VId1s8U$FYmbX_e=Q?V7~jh>)auxy_cX)dyx|@=g)uF32iuew}?H;EhlAWE@;Gk zTxt>hE*03`sK%UhY{kiE(pij)IpbQd*0(<#HTjf$VL`4I30^L0bLluvkXZy(O{eV< z?dtegE%YCK|L?zfe_MG@lb9nW4oNik;wi zMQXE{&ia*zF1%!q$)pq9-rK&O6DlJx=f$_)PEcp_Z_h7nSv(rPekxeC9e#ehmF*WT zym!cghM|-TF80KN@RL8veNf9Yt2Y7EJ@n4Fg1aG}Wz80x-M;jqslc|oM<{maGMLIf zCQ<%LmYO7CiVE-0HGVzBbh=4$<=(qpqmN6p+rJirNk{qP3^BP~o)Mno_4AV&jn32K zh^Far>n@JQiZ*wi=zG87$@_J(?f5?ur88N`!QVAXugkkgL!c(0(#`vY3B=P9>w8T3 z{Gg3}ng>|nhsX7g6t`D|Tb^slzn073&6h+jie#oa%vhyWmNI>4i-f> zKHnGaPk$HfJ6>OYfi!<~bIMAip_(vF+}$xkCGl9!dgyCp9FG!ub?y5svtKxa-0U_1 z)!Q307;)TPX_)g7=W~fcw(3v}JO`*TW%3THTNt!Uwt}VZ^8{>I^ z9XAr3NyA=vfJVl*Hhb$PHwvy>{Oa?@{adMj!|oF2$Kl)FZwo4@5A#L6TVEO6euM?9 zHNQ!}Xj+hP@oh9qu{9ahFV&QnPr8*^U9ua~+s`_<%9``qDziAL8*Cx@)Hg=Xmt`>9 zzd*`R@Ty=D#nFK};$wM2Bf0Mmws6mJ{>|K)a$r4NhQo)iY;b9NH&gY+oL#|FEyrYE z*c`yhLHI*AKDD6tmlXfAr4!Dq)+c(VCGwVzSCIG+<2{YrVs!!PLirrk>gI(aeoK)# zh~1L36oUqg4BBiUI}%eg6Gp07NOzQGL|;H;$oEvmkm9Yd1Krwzz;YTG5N*X3XcD+ycL zh_3MlM_Sd=`&Q5iElk9lZ-V}DbROuoxiIlk5CgJnqDji6*n()~UW{3kYKpt-E_r;o zEIDs{L-4=>DNvT_78K;u-BJ@LK(GuaHX+i&usI@zYfjsHrv@QRUj}oqMh}h_NmCH% zxJ;7wn*xlP1FIwIMCkCTuA)IqfIGLWyr7sTT^KzI2yyY4W>AG^=kn9`EwyvJ*Q?wk zfc5|z%SB>wzxVAOGIcZMWMc?_i_{O&#buny*2afm0N8&Q60O9<1wHlqWOjx{pAiCK zWFp=Q!=Z@@?9X-e?dl)c+5hqp)tteR`cPmPJJKr?%%UF%V}*mE75B>T$lOk?$s<^{ zrRPHuAS4GFh%Jt^e#&Kdq=R=UJtN%2{42u^?+~8{j>*a4&Exq6>5ix*|5kmT)b+|h z8ILqv{LoQ*wLv&QX$jnW?3ta-ks=(Dh(;&PnI|7fVJd~4<7DGbT8c9!V9{#>;< zdrvCnd^VsNY)J3edh5+Vt(wJmGQ+SO-mA`pPk1=aA=jo|x5rcc5oEL`j3RK{=l-`Y z{Oh}Lf)?E^(_EjF2FkE*d($#AW<-)YGc+)>$Q$*g5E@+6p?$Tpw6Cer=Di{;LnL>y0qy&^cY9}W5LRDS z-(bXVeA+65`r~;0DhvvRVr6rD`(hq60tR6a@RZ$`rh`X-lGoxPMC3iy`U{3 zZ^D*WdhcqfEF-#9C35Mim2jPFSX#2j5M0JAe95axte*`}SlHB;G9R70w;JP@oE&!E zVJcbO2MFFG6b~hWJF*JDx9^{0HJozGGX*_!3_Odo^?o=j$gQd+Uk6i#f#$X$clfq_ zh9kP#APa^1)gQ5|(42s&1MBD_rT$6dD$Qo%JqgDFcFcllvI-T#RFll>?wp$XiY~@< z!Z`v^ytwa;|D7+_u@iZrD0C@5>Sq&znioGb1~Pcv?BK*_t1mmm(cMFdb?;?aJDJZR zbEIc5v|VgX@M&+aQI@1TXd`6&y77H3O@{rNx320C?PX67Pn zH#%ILY^PWV_l9Vl^JRB-`()-Lzf2;$1K=v)<)&VrQNgnACx0AM|MmHS+T=)8r)Z9T zZx3jfAwZuj&Revz)FZFWQfTR9+LcaJ+Nd&r$!#VF!K);FqY=Ah!&Y3ej2z2T`x<<% zNK;+Gvk0aX>Sx?} z{@v2~T#a%qyw+i{cyAyH@xNGEARS+W&AEA z53BWbQ$<4BS)6gq?Z|VN6N_rk zPRSH3(FCw&8@MOG4Io8nfh5}tihV*I0)B;M&_;R&Q&kLi(BUr8`Dj9a%Ni=cd+_8> z-PI++GDKwAtghq*V%H9ga}S6Q6Yss6R79oERS&b4jiTy=u486$w4vJOx<_nTbXelz zb)4gf`iiCMJRB(%^Zq{S+(=KbVA=F34_v@|U3Vx4{sm0e8gJ7TEbA7Ga;0A-p4;@aQOG+a zGsJy4O`e<9OyQ;!oz8h7q?kZ>WYDjzdFB^=v-^l9L}hJ^_3=Yp!KVxJ-m6MC?_7%x z{>R*N7vaiR{v3X}Rhx_J1fkkd^(7DfN(iwNn>cl$g-z4iXx-8znu5&aYmpm~=j+Sx zKTpSW*;UHxS14a=D|N&P4!Bg0fjChlRj8rbh5#z5EX!sC_1naayYvkIl`x>x0N+eQDBV6BxN|PJj5C zt&JgIUR5#(Q_!$=osUmhNX>H3ozAbG24z;GGk@st2lUfScYSOwwHFR2y{md`5Rj#R z?b~2FcQPlV_!a9mh%RNqG$KCnsQ!nwM)^eY>uWP8A;BCQ=H3F&cqUnWwg&O4^eMqD z0IPC@!_mSClIPo@o(SG3wC#S|dRu48-Ppl;6K5Pef?%(1N-3IK63zM;^W^t2dy~Y_ z>Ste=v=C1eciT=Tnxrm39up0!O$B^ZRgKC#jWdRW^kq?~u+~_^FfPLpn`Fb@qGS0% zi!OPIYeI3Y_4(H5=qh_ZWDY0Du61uNI%@kubq-*5=ho2v&1v*|W&i!j5s?2qoTPW< z{a|`Ca;>iwmF%RkT6s^EYsFI74b>`g!-Yy@PN{yZ2%(ugP=U%R7MhTlPFtL6`PV8J zm$W@u1CVUxM5)CboEgxW#ze43R{Gm$MYjB5FV)NNn14aR%BAFlxBIUj!IP(5^(w%% zCe8s}QVU2FGWe$BWsg{IMf8$uD`sXI^~C$v@3s9qo7%zKo@J{`PXSQt-U~E$0G~q9 zg&#)E!@jc-B07fZ?tE(NH_G^oX<&c&@DSECZEeFJ&j*@Q*@)%R7Yx{U1AB2i`9qs7 zF@qthAk~BV4(gDL)d$Phst`SPudDo}%6pnCTqGSR3yw%`bTkwEYE^6t!YOMZ+XdGp z#M#qs{838j*|0ba&zFxVG@X;oA2BjS?eK;K>MP2Mo7HdJ%%uo7U;aZ)f9>=bgOesr zbvneen73f|q_%S_SJFh!a!0|Jb=#OFeSW{!1L)>!bLk5j2vui^75f<3%ZN%LTRY~- z-*RO9R{bGqPogUftM7N*Sp{Oc(|IwBk%ci}9p$|Sna}7`*@&z4sXh4lx4Zv%Jn?F_ ze-3|n&&748J!I@->;&5n@WL=(bio|c^MmekGz^<$R&)c94z zA~hh6-n!_T>JdC@U|@>gVS@Lqr0@(2{P8C zQl#r}{lM||98PPZ0k23bL?FZb49)t+tR1&j9eu(?3kV33j@rO@53j*}+{;e7W?Wd) ze$Xo7xnAH(Q}wMN^0yn^qI>vIfG3QzJ37MZHlTTm0%om&jL!9F7^$gbV0mQ;FB@5?{7~ z03t$rdVU1UW!?@~npP-j+i-9ZXYEL+_SR`yF{0#Of1>&?^TE5bc4w}(l@)RddM+uM zDwroa5e#HvoXZpPNm>&g-lTIV4b~dlEumSXAto-E=LP8hv3dW_*mn5ojQ!l$k-eVX z(?%*AI=*J&s=t0K;6&b>=zQyoq7Qf3llGog7#Ozoy30@T#yGYQhS8zV+vaOdr%mUK zeJl;DL;XvQhe!|Po+ZvuyRgn`s}RQw@9p**VuF4zuwMinsN>P{#VFVGLa@bHixE!_ zr}=0lw31XdFjD7!{BZ*%F*sI`i-29?#OJSDK1UUR)@lx>h~Vzum6T#s*9QrEe2~!p z)Yi!JdJ^Rt=@eU3w~t^q;h02C>2sneaE};=d%vo61y~kUxFlL3 z1cQ!L`g>Skd!S0eN$X-&d{Q|3Ueq;6J^4Si@6THu4yJ6SCfWBZ(000ZY_jaWGBi{2 z$5i$TG5f|?;WOWjv45=U^C?o!)@H_x&AT3o>q(zRUzx@RG{>gE#^U66NWnQQaLvLEt^*Te5#FkKxZNJpxgAUm1!9zcOqNS|-))`#+3z z;{K`3Zx_etjny)x8bg4YSl>DtfZqWCb{0hzh6J)9vB>)6c3Os{b5f-IrJuUnPTx~a`rZ7`Tz=Sb`d>WAnQ(Hb(-wiVO5 z^jTd+Dc+UMgT*1~)Bjt9|LPY`m&taACKo6>%T_;}Kyv-k4Du|8)N-my>72tp|E2SA z-lSrrDnJVaSb^rQSVH`I8y74AN$+&7v>9-Y^2D}_+RLTH=b%y(V5XJkytaa3wh;ss zbIejwdzVdNwPTxruD&U%pSz-cz7U`muHF#*{6B))izd_UW{S5)kbZ{Fh>j@U_o~aQ zcf>Avm-htrc;!z}syqwgO;Z-8maKf-870d3*vm{^jOI9tD7NMLweSj)nUNgKJ+&0| z(~1fX%;Mt8ehpG=8KJ-8-+iy+fJGo|;-Vg7{(Cj`2n)ygiW*)e$z;|*mOV3jx8@!M%Y}W+3P2rba%RKUaHKQ;nklxcZM@n}6$u)(}kys=jVX zQ~pG>0X=VwuVwz>a?4f9+QS17*D1Fk2gb)sCqM~I-yNg>({54oY^rA9w^ z6qcJ`BXWXZhlo*n+cXN1b(A?SXR2O6;1Ptwox|r+C2_^>1Mc}TML)FCzA6I34GadfL#&{aN%ls(OY8ZlR3!e zWJ96^^j;^(E7bc^ADjKG^5lCng=&lZ_@%LWqSrcwOUyuRzYb^&MzFE-YL0oDGhBh%T1tUii1_zrf28F23Cc3IgTa=n+ke|iPvLyF zLr{j}o(L?&(SqN;tt5Qa30cvn-ptOU^!$@nz4I?ELpwGhG=CrSw86*Bti6C|ep|F5 z=w7Rz1HL`Qm^2luyI@eyIm*0q^-YoGnG+bK*NE6NL2frkfI?&z9h{68czLDq#wo2u z^QZ}F`D&R!48i)n2|9l=2Ng0yf(bKK6gz%pU}J^!ocrEy=MCqVr@iNTF)rF^c5AaZ z#j~|2{dGU2Ot_`fWe5I z`)(g%Ls(zv9qkh@oDU5nF)E(YuKDrA8Ll8<(rcjH4O-(5S!O)H-{hMXl>t$S-i+4Y@-W0B8b2T}0yUr_6y5w#-wfzcFxZ=K&!XMg^aEa*`n ze*-3!kcn-rR&{+_FpsLaeF;cz5y-k=L#IlU0wMa}9N*>Nb**EU>W(1k6Fu!2r%GWS z92hD~kdudv7xO2uTBJ*Uq@I4Mw4yxN4Q#?eAXlr=N-OCA0!uVhdnx@VN2{3h%nQh; zHb$){$&mmntu!lnp(SGDSH#xK?uI10@)g~OScww^l;ZtjY{^BvV({_?-8|EXdwsL! zbnEu0RTIgaobtAEEdi{xO)Vj=UG?rIi3rMRsb|u#p*32pu2qj)5LErg%X$-7s`+cr zxId~ZHxJ&Y=c7pV(t!wvL9DOPl6)ydVtf`cu?{~PL-bXjvTLCdQv^4CowIe+ zT2%@!Xa4%f7w<2eUpK;f_Gc1QOuD4d`RiXkUHl*5AI^FDRKdghAqQt5=Z?ZX5Xz{L$NYoTR; zga+`Utpn9df+cR3fyJ&WFE1nzU|gP-Qnj^(Q8-1e>UhR9^Yq)5-X!5FTL{sNGWSG} zWnZ%83(i|jFk8ucC{(_pw;q{$if0YKJH)S6jEKeJD49?p*^Tz~c)0Y{dnkwBhEr={)J%omYTEMSAzksp>+%Y$JB_taRvsZRV%>t zvdOq-7d-`NORjWkjJSUDn)f~aqj6r*kKU~NOXnLjduCG$q6BlTcvW2JL#QOYG?-59 za`WSxYfu+3K~a!vvaw^EUPUMSq6`ts4+%`COXw!f7BN~C z+J~tsTH6&yU^>I2BhfKZ!=LFmT|-n==kpFr5rd+Z+9HO;JH|>sj#&jl_2sslAc8lxa?K;E5Jss4s_?k!=K{&}j^R2A~`0~D(-?xh^ zxo3;b&h7$WwJyljebuYsH`VL6TmHiF(vfbWGl4QolRjuOOY1}mtAT-Np=u*F;N)*5v*B?c<0{T zZRl5q-uT+D468SREG6&e)Ir3=>z!6#89)io!_6r7yp$zT)+VEO567KPmZ@Z4L6u0K z2Y^GN#rrc>IG z`fVR;Ta8_BD}Jjo2?5gO(El+J9=jVi@VR*@^(6<&LUMgp5G8AgneELB>2e1(48f3N z2VYzb`=WXE9P;87cZ}L@q~koG`AG1vZ|rxzVi0@!1UcB#mU6Dz$W&0@urUnXa=c4M zkA-=0NR|mlYe!>I&V-LfB3V?EfihFHk$BRlBIS59+wkNUMMtZ(*jmEOq8oZa5}!SW z@~SYDg*UjGeT`|p5l$B%S(_BWi|MQ*VbgnfCv{NCyZ1mPc@g%RomhavgL zHlTon2(e8|&ZjUpN(hE-;C@P1!NYIL3_f`^I@;H9HewHH)%Esd>Peq!i+<;H_^H@%&H05MMNI%Wx zITglxP!_-tqpdBdkYFAX0oVd#iKS|Eb*W&)Nx{uq-$Vp}?w9>0yZ7xoxou9GwqZxG;%n3Z-);kA= zM-%x?N(=0k*if2|@AbhAc-qj31g&(JL^#O&DfClX7b{J?2$)iV?ayn)R^~n>$~;}W zw<;RyV=QCG^Iu5n55X5Q`H;)U*F5 zSwULkf_g`IhU*;brMZ2Jdf}%Z7WJcIy@6aGq|^}in`w;O+e{1Et4g2x?^Hnw$==Ac z{OTQEb%~%I9~Jg_=fZaA%rm*3oO~QPiO)Rz?j$Tt(lP$JM3j^%P7R&fhqcvnhDz8_ z2U#8`Qgx%Vf7cNHA3rq~eBa*nt$?UAt)pRphv;e?3tWXV<-lt)1}(0)XpU!EQs0Px znB0zOc>?s+Auqj|+4LtCLCH2XWv7*E0sB;`t~a(v(|DY|{v2`9pqDZq&-FrDy>h>2 z85sWbt9YsImGi3rxSkHM5U6n!vppCtF>hxkA=TpM08MO)FZ%$5v<^I{{P@yW24=_p zV3TOX_^thlE=s7CGS{yf9;zak4qT};tT$RUkA4S{r`r2{Wx#Vp`m8c4F`caX9p`q~ zk*N3jk)o<;N)AS{&ONL@wy3;h@$e!AFya8;W%FG~+vin_*&;e0FS`)jKr&dao7{Pl zze0X|=F&))%|GD0%nL^7=zq;tEZ$$*1`>E= zqW(9=?)y!D+x`IOR#qJ>etPfrRW~`U9di@UOz?22p*Lz6{t{me*_P+tIUaQ_UfI?B zd({7v3ez<=TquX}4~Q&!F?eQ_iNIy=AyYx>xRnHr?3o0eAI~^)r?iR>0L<(Q`KP@c z3rJnSd+&p4eHUWhtW}0eX-d5OS*IUZe0Y zP2U9E7jjc5?_rT=JTohsmg5#11}&JEizuzwLrVHJJcyC?dLV3a+D!1FmbOcE@ zMV2?lSj0T?(#rgE6y{nq;sd>d`4$KX(g{?Pkf8DR81y=v&1HGUV=Wt^WFzVYqmg#o(Ju;K2`_jWcNm3)G1nk<)> zBqe1A56@)f7P4q&ucx_-*{Z5i-ZR58tl}>yImC=Y#5{{ih|Q-AQEp3DhU3mHZFnGz zzcS3-5U&c|m+Fu-eLXKMmz-o@*#{O;3}2`o`9;iC0CaDBOae>Su+^A==n+RbI`jmZkWcrG zu`W!fA*CcHyc3*@O0_?Ty73L!T2-)f-tpdHw%*R<;iPKUp|8J){|87@vYdFYU044g z+720wYAk7xf$C=eTAkD{J#&-QRV|S0n zDk!@+B1L}dszye=Bl_AklW+Eb&nLk%+R(A~rE6bW>(%!>tr&0IgluyYDJkPmjn=81 zFUt+Q0dpaZXofd<@L1d6n~~zrJ4hIgeObFU-0azA~@Hr_R#JS{= z&Py=gP<66NUwYsXZ{G4EYwGe!arej&zu4mI(OGeaYx_^|Y$@eYLAlvO(Y~2s?ME10 z7S+>+L2({;=rQ~iL4B2sw{V;niSn)m56XQ8I8VtWyI!|Rz^oYyCJ*1J2uD>jXXr^m z==132B62Ld*eT4NTl}khuHkv|(7crAzgczlzGUtJz~LRy>Aw7Fkrmd*BJ@20xBsE}Uh9?06r6MQ_%5zUdo3^{I=8{=5<%%~(3o`7xCbw`rrR}mJG2{B$E zRXS8{(MZ`PH3ix26fGcL`l;plRiIer`d-`ruf6Y#Yw~*gr;bu_m9kXC0U{DsL4hJ5 zii9a3kPtQ%f=Ga%jD(G~N+Afy2*{Qo5E6#WNWy4UHi(RXA%v*x5E8*KWcl1!ZT+{u zKF^z9?f*sZ7xy{IC+A!vCnx8=&iDGBIi;1pY-scB%Y1^{L660dSj`hm(p-bO=1K9KgtuN3ke{cU4LW|ymF}_-ah4{#FEM?bw}2-Xr5q(wZW=#`c|U^q zRGgAox0Z}m$X=M9C9vEgX6cF_R;suF`bK}Y{tz=?oHB=^=Vi1JcR0ierQ4ibLo$+G zu^v$5L-i@ewqq)VvsG^@U&CWVKoRy(J3J9Q^58e;1D+DDw#wfn^_@{^V8yvxa33dg ze`W4DouR~Db$Bd{lrGT#n$R|4h|8s3JVjFLJMfOrx5I0`rvfsd%QPvrjBs$W3E96boHf<}E;L%-@c ze(k9(R?I(ctb3t`5UK^S?#x&rw2^w01lpw&@$ZE$+_m;e^jKKQkZLMbvF8XgvYGk9 zb4qN>NE^YaRLMDh_w@Uczc%3B=5p zSJ&g0-8fF-ua>GlJ89W8GYV;JGZl~w-vE0?e1jy? zM9$_RSVP1tZ@2aabpN1(bYgIOYM87vw*BoPZu2ClC?R(K`g=Y9a?6Ep>sT2szxLUH zJu%nKR3y~$ysa4*x15h?krJDegI*Lcr82aLeY+OlV7gwBG3tQ>pj3iJ-$mnbyP$*k z=m|Zr>#C%mXN_r%l7Pv9592lY6w%t(`&i>zxl1tQ8TFbQt4S)0vv5t4JE6b6-=29h z3RA)evn%z?wydc?NiEiaDkwa3#m*W(&)7&RH!ksZl%x0n(6-An6^4xGTvAw%GMjSz zS4-ZT!*_b71V;_MmpvFnvT*dK%2tDS>s?5fDJ(;2i)cm+Zxf=L#U4#+rg)gzd!$mI zW8tONq39)Jng~>9yI>M`4vN)0dIfuV-{Hc}@TJ=UdvDR^#i0S|lcv%UF<=YvykMEO z0K+&vXX~(po<3>Y@}uhDwYA zP?!NC7WMXtuA04nYcsj9Co_5<%~!U(y>NC(p?${@dN`BR^6K0>K8=VuxvIiI6m74i z-O0FKGVVfeBv+CC_`Hw7fQjVBg6Of=L-mcbhx*sTfAmnl z`@rnjtO>HwF;4aZWMZYY#4!O+7(fFMZikvEnr+IK4?BN<2`K>vg8m^qFDqd0jsQ;2 zg+#aSLg08DLM9!TgoHvG5v6UflyyRZ#c==KWaE4tj$+=O_hVXtG(ux+E*mifTnrezZDoqTe)+8<^F97wqzWAqF&S zwTmDGHKaLcuL{+5nCvP=4BElp4xLUmkR+IHr6BQ{L6x_oGV+{mO1lPIQITSqtJQ@k zUSAzfcT68Jkr@`*3w@Qn-K6Hlqz_M;&Nk302KLM>K_FyS&wp*d?2mr<^J@w1jmMsC zY?4;^f{BE8DR<|Kl0sh@l(rg!vZB#wM93N%1Dj24mjzCYcRWQoS^J8lX!%%RxdyXd zSA8lGw0u%#l-|x;);<^s-p4-jhyH*4J#70k#A@?%^Jz5_Zr$ZErLy5aHj@~xugXko zA4>+|vZWmtLy@$ucYKM9(6h2uI=__J`C%E?OlH&wB%KM6g<4zzKRU8N=|z40;sSWS z%->2f{=nBCM1OIls;p?&>V=f-k?O-0UUoW4ts?Qh%kpEGhDi&?oMJ0Jst#vL4b@%+ zfR1Qe#k(_c+X;8{J0x0$%c7_O)~e9v(=}2sH$OoUdpT{bp4t$QuYQ>e#jA$>NcZdq zA%AzVOQd*;N$fC;OheezlRIKUPS zRx1>Fa(d2_TA z#}9{h$Vlr$B#*!2Gl?0bI&r}OlIqgKI3LU;>LGVuJ_j?WyU}gKs7jzLCF#!Qh&Kui z({I;0cG-q!4J}mc%W*7FvC|E*Sw?-x(2Zw-hVdJaPz*gs|PgzrgNf@tDooSG_h;eu(x86}sioG};CXuU_} zP!R%t6Ekuv`RYfZd-!-Z&9;e`Qf;_4B@^TpzgXY|t-YgN8F?uhHk2BD5Drv5YhBt# zM(wZ>O$msnwFXrJ~Cl_L?Vow`=bw(-i0(WYb&OAae9 zGQc7uRzL;w1;w{!Q)IuWVi6~cp}Vqf{L2ZAi#nOKfJ7Y| z2O@=7gwtEu2^?4uCi3=)*}-KynTg^@Uw%m9{;1OzuIqcA7ZkSmWya3UMNZqA7?{1| zBMs;JSD;qUO#4KPn%}@yJj;@{{@4I0_wZe>zrY)nhNmhR{(L3HxR9%65vMmYuSjpR zH*Q|34THNJ=QxgJy_Fo2w!Ibfsl@&6Ce?YWy}$t{E~Np`6j)xV%`j`y@|Gb9~~Rd*LY?8^(cX&DO%V_{j*4YTaBXei1HpXtcZ z)DS5GFo#T()zKrLDEaqQUs{NWh>?{DUpTDm`?o1H*hhvH@D9$FPM$dz^CWAU(ZJ2V zaa<;lLLeVoFLSdF(kiYpuKeoAuc3~QYHgV~?bif<;vcaWhc_iEUM*>^tQkQpDd>4S zH$Tr37mL6|SXzdb?Ruem_G1&EkmqNK%#bUncs7pJfyj84wF3jD^xTyhICa%3H{pSupSYiTosC6DQzsJxwUk?Jke(%@{SkGJG`q=OS2vt3`{s2( zrN95$c5rYcR@@|H6)`l`pisx5^|wRPLIQ(?f}-4_B3wyfdSXQ^7gL&| zPdpa4sdIfCXHeD34J@Dc`gaKu1Dbb6luf79Pwt<3nArPU~Njsl# zI`3~rL_WhMHBjaMCI-=@mAX$$D?%mu%tT{(MosvMx=SUoY7^Zr3$wCnpopusz+7JZ zrt5S^)zIr1HCseVB+SRo{iIY$ljqnL+mRgq6EF9r+y?`vTybq?o2; zV`hs6PgqDl^u5<2h-Msh-C*O*f6AJAo)8uqZw{7|(+&9~DEq73+mHhrS;`FSNc*PR zx#uUZxI%8Q2G+Wqh3C&Z9zZ*f+>d=j3ZIsg{1#XdfEvGj?CY@Stwp?>TJ0ToM7?Yqx90-W3dq0oFP;GnQ_e2@(6~ytVpkh z5-<-3gMa?5_rJBmpV_V~@1t7P<EuyEm9(f#gmpgeKqHPa2TrY z6*Y)efO5@p&RD<^^8wLTA(^}B=)f!e`u(bEYrF4rqHaf^MWbPG^%U9fQw(J=hVHkZ z6_0q$xXRuOm5%DQSNOWc{5*lHR6CCm&|<#NqF zyRv{VA=ro%LXoMdOQ`UfbKdzx&y0n)543`Ngd7&nY}+?A(nJFQCm>L$h;XvbolQgd zYksa;lI_o6i|(>!N;`0@OWa&=`P%Zv6!`^}6=eW{QpeSo%6cAX%;cpS%bzxiHE^v8 z8+5j6Hd&bK8dZQ#W%$wqUW%h3u^9x_Gm5^o9kD2@|KOslcnk)Ufm^vJXaFT&e0(w@ zh~kpHXMds*CH0Z}%9&giVSKJAjVHovi1Demd4<+*AMfThs`bgmKXj`JDw4uFB&+L( z&Po`oLN(55hM@Jvn}*?f^dzCp+}{^F&VCTdFR;DTzmO=Gb*Zu3v&pzE>18Jz8N#5j z@URYZol%=rU4S-BUjv3t#=f$wx_SLWv%kGizKq7L_~1*jFQgvGOB`2`S@GSr6g&p; z5he74D;hDu$LcbcqnVck-yDi^H^qeuu+is1E^i%keqbs31;94U)>-%Xge7+`!Zjb0`*6NMKn0OL0ca^70++*&hw7b!6~y*DJ{5^TMzv6tI-d~g z*P_)^N!SjGr%G1RsNkcy+uwAF{3KjuNt-PX$`baV14y3QgmomL%4wE|ws-Uk9JpxK+#wumAeEFP0R)nwiWWhVg;$Tn5&aQuq6KgA zRZXKiC^=Eows8imH?Cx6+`PP!@QzPz>J|=q_bh!pa^dzctC+UEqN2wi=Uan|M9Ce> zP~0TZHv*`>k+Z&NFhrjCo{tF_5?hZ>Ti=6ur1-gY$ZFXh$&dI6mFxL%wd-Jm?Mvqy zi*MA!TNkTG@Ot@Z(V1HkLrkzg$y@@uz4^o>t_Z=QNn)dxN2seJBEmRs)!#nC{z`yk zYy{-)hD=ed_4dqX9Z1p;!Cs>BSb^(=i}GuOm>b~{B@Pz*yn=0Z^Nhp-#+Emwd3MBpLu(|w`pmI^VR9mQ2k zCx&u-2f_ph0Sqy$_IWKfCz>qD<^t*Jml_^bE#ws(%rNaG9%;!@GmmU(djrWkGn0Fn z)fk}HoiA<|UDv6HT%Gsws99nLTo&}gI$VD*=juH>euD$Ct4ANpJ+Qx7VxPT_W6fn6 z0Vn^}HxLNpkxpKY34;5k?f^V+iMnUsH~9x{R$>-R$J%#%Zyo|HdQo+Ow`4l&8gf{r z*9t^BY@?l|3vPf%fU``V_Vfpb)6F=;HKw&d@GdK%)jYwKY)ieoJ2PLqQrh3f$w&q( ziBIC}9}FMa?OLNxD16Zw%cT+KlXfDp+df?w>R=HXB7`VB7xIp8VtYt{Sl_`@cN|su z%{=UPeJ$C2$0ebl%k=pik%nxO7j z>b1yfJoEm<$pEhsJ#M>~UW%ye zRk~T4fHFUouqP_t9&xD{htEzdO>12VzMBmY zp7oJ6;xD&T&2Qj-ILRXxAH4CHGvIA_!y%$&h5O_+*}fwP`iEy z@aBU|6SXEkqP@>P?0n?XSz=Xu^hjV<&Bnpk6!#~yl(`TK6fI1c&<*+B1*cc53Cz$M z7>(1P0JB%Tc1D1uzT}l)IHClkM8IeaZL5dEg+y|IV?K?_6f5%T&UINH08PrQGzk+L zc4e$NWXSu_Uk{DSVE1(%dEc$MQX(25&(#YD}+Fai`$BYjDwr290w9Rijos-kSa=|V-Hlre(4~&6~zREf{1j~o69rg zWp6oEv*}8(y@Buj8x0JYsq=XtUrhn7;pJ5NpTSx9y_D zrP5f9V5k)};&yW@@A`X7KmYA72l%EcMkOa$F&ceLRJD`C+GEj}j`=V>0v5s^ZEBdY zuEPpaj&~*;WKh&2*P`y4%}Dl@IQ&w5CK_}tO%v_#1QB&+z1u-mZsc3R z%gvNPlb6KZ+@R!_h8+Lu2Zqb}vCIbeZHTYZ+zFwdjLEGJ>Afjk1mQBWh5F@_vIU5c zK0zV49l@Vgv7v6zL`T0`5}CI5-)OG59idchH8Mx6-#sx1i7Ka_<)PY(8h3~TsU%Fw zp{R)!&{1gC@_XaA8!ey)3aTBUf`X1gJrJ<)Ym z1c1tmgSln7$+f`GXT^l1nqyTPm0nDo5%;yQd<3LJ5Obs92H~f$-MX7};_)BOtuj0G z6H->xK4S=tT&S4>sWH@7Qwkrmvx%z_boxqr`?Ct)f9h`ySYB}dmwfpz;e8ST-Mk9i z3HFkhgV$G-epgk*w5&r+qtedTx#+N^XsZBvqK2km%`^i(1nqa)O4woQgUP=(TmaW| zK$c8*aYx(QjC3xWMOUmyIaeUdtAM@j%DEkU0AFR=_A=oIj0#PviL3(Z%3*DI$LfF# zP7)2%KzUjS1wetw$o741`?ov65}hmTW)n--VHPk=A+oZ20{jK@31hkN)p;rL++PO? zRzhOfI>zQzfq_P&yuDlzRZtK;`jW~fG(^AATwGq{K_x>Kc7A{2!6#$tGgi0Adn%bc zpU8&}!Uyc8uXQ#Tsi&jm^7DuZ_*g{$6H0ANlVBYVLZ{j+Y+}TTDGBq2#oi zO%mICulRYM3KdMIaw6*Wnw8QX44&+sFk@=bP_*xGXmBja-v2?%%Co+m8TTTWkZsqB z4#mz94(|jNJ?FHJOX{+wl}p zDE0b(vg$LV(*KhRpT76nb|U>!dJ@te>F8GY@TzAb=0%P=K!Cw*&(3W?E$KOutTlZ! z9kQ;MhFMRaRC%;MKlf9^g^q(UnK4_%n@3F#D-6+&_;@Un;IPMx5W1Gy5WUObQQ+m9Ip+Dc2=4U)k;yN4kv{>;IYUT@kl56wI`Z$#vc z$st?$B*uv|(3V<|)mT;3G{7ZO8TOLm`$GpAmDJIAS$h>}ABaU=`VDUMi6Q&nHOSXdwK%n^Z|_E| zh9Dcbnn^&k%IftrOMEP$AqN}+q|SzjLPu}>Nt1+i8Ow$|`?=Z!an?P*Tup)MG2u(H zl3?d@4Q-+2MIir6bpAKu;Xk$hEN}3G6Gp$=u=mXFN*p>-rq-T3WNiC9PLD}Ct~ssT z_S#S6V9xd}U$7eW7kExU5@CC)LlHWJ8QotmZXq6KQ5B#F@Pw6irN$%(YRzky=n*US z4406^Rl}gA-1AVc+KZH1Zrj-Ymd#_!+VOgj)rhEyvZy~8CUhQWqEpBE(jwSDG|i(r zP#(q9Hzwn$#76p~{X)xF!v@$B8 z-G(In&CI;e-#0(snOR)tmdYaS}69mjK1D?l>Q74pdCYiT9E?7ARTb%k-qyE(o9-|+9(c(H$+ zmzQVu5<%)fG?`Ea*VEg=t@>$iIDf(ONF^rC^0$W zbHKw&RMQtN(-wcB)NTjNCvR&X`sarF)C_fqp8io}{$-Ij$uHlY5%N#$!rFQklfGIS zJy-(p6R&;eW=fNaxY+^{g--nZo1xooPyc8-sMAk4O>WIl_-W6}tK@m`tG9OV_#PH* zG);p1AZRzZk9oPMOoc0%`M0J8{HD|YS$VVHN&L3EXpwxaV@l+LPdKY}+(ix-j3YJO z(0il5jt%XEI5%$(K@=LG>EA#`PW9rv5(h@i!nM^!hmRuE6PK0P?Kj!=3F0z6`ZZvN z39|T+7}Sz_vA@f}-qgYXc46GjRKD2XSATKQx*nK}AgdxfL2Dn?VzUQ4v(KYQHtZ_j zVMUUy?e5)DXOhN(+0n~MuL$+&83cmlwo*@U6*=DMb-GqiJf>jwA~&cNxr=$5>VuG~ zJ7cf((*a54`Xqlda+fpyv}WN-+Sa5K<+`hpt#_Cni#N#H zNtb6Y_A^>@>JtujzeuXB*y+B$Z^9aFYWu_RbVWxv*H596C@XiDu~s}b{@Ts4-mzVK zuqSJAbDlrORHiQ~+tjRKy8O!rmLLU$8-|DQF)c}!dZu(TfEtd5_HwTKZkiqJV7|A_ zFQZ;NMx=_$;HZMK4e4XC1WI61YlF@695HQ+E!O$>7-#JKv*X7-^QO7`oBRYpr6-sf zd9LZ1)A+aO1!i)FYPT6(wLT?Dv*hdFqh$ZAS2v}fCe~xxA_|t|X0r!_^PD!O0g4Ji zpBkp_{tpW*ZLUxO>m9~p84ddPK*mW*?SlN9iDc? z4^e9{^{U|<@_a#AVM;uF*<0as|2&jCBW^Xfp41GzI%_(RZh{<1Is;{ zq2W`8gSDEE)Kc|EunUZ*2*s}xa0KLdEp5@fxekGi82d3$E%iQ$7f_5PWX~N^_F#@` zqZKHH5w)%v09V+;?iWM0tKUo|9mvhjCaScTiY=B4x>fh;CSN2jat1GyB^sPuXYPg# zl5&OIYD_w + + + + + + + + + + + + + + + diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json new file mode 100644 index 00000000000..a3046999279 --- /dev/null +++ b/packages/web3-rpc-providers/package.json @@ -0,0 +1,64 @@ +{ + "name": "web3-rpc-providers", + "version": "0.1.0", + "description": "Web3 Providers package", + "main": "./lib/commonjs/index.js", + "module": "./lib/esm/index.js", + "exports": { + ".": { + "types": "./lib/types/index.d.ts", + "import": "./lib/esm/index.js", + "require": "./lib/commonjs/index.js" + } + }, + "repository": "https://github.com/ChainSafe/web3.js", + "author": "ChainSafe Systems", + "license": "LGPL-3.0", + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + }, + "files": [ + "lib/**/*", + "src/**/*", + "dist/**/*" + ], + "scripts": { + "clean": "rimraf dist && rimraf lib", + "prebuild": "yarn clean", + "build": "concurrently --kill-others-on-fail \"yarn:build:*(!check)\"", + "build:cjs": "tsc --build tsconfig.cjs.json && echo '{\"type\": \"commonjs\"}' > ./lib/commonjs/package.json", + "build:esm": "tsc --build tsconfig.esm.json && echo '{\"type\": \"module\"}' > ./lib/esm/package.json", + "build:types": "tsc --build tsconfig.types.json", + "build:check": "node -e \"require('./lib')\"", + "lint": "eslint --cache --cache-strategy content --ext .ts .", + "lint:fix": "eslint --fix --ext .js,.ts .", + "format": "prettier --write '**/*'", + "test": "jest --config=./test/unit/jest.config.js", + "test:coverage:unit": "jest --config=./test/unit/jest.config.js --coverage=true --coverage-reporters=text", + "test:ci": "jest --coverage=true --coverage-reporters=json --verbose", + "test:watch": "npm test -- --watch", + "test:unit": "jest --config=./test/unit/jest.config.js", + "test:integration": "jest --config=./test/integration/jest.config.js --passWithNoTests" + }, + "devDependencies": { + "@types/jest": "^28.1.6", + "@typescript-eslint/eslint-plugin": "^5.30.7", + "@typescript-eslint/parser": "^5.30.7", + "eslint": "^8.20.0", + "eslint-config-base-web3": "0.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-import": "^2.26.0", + "jest": "^29.7.0", + "jest-extended": "^3.0.1", + "prettier": "^2.7.1", + "ts-jest": "^29.1.1", + "typescript": "^4.7.4" + }, + "dependencies": { + "web3-providers-http": "^4.1.0", + "web3-providers-ws": "^4.0.7", + "web3-types": "^1.6.0", + "web3-utils": "^4.2.3" + } +} diff --git a/packages/web3-rpc-providers/src/index.ts b/packages/web3-rpc-providers/src/index.ts new file mode 100644 index 00000000000..eea79f433cb --- /dev/null +++ b/packages/web3-rpc-providers/src/index.ts @@ -0,0 +1,25 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { QuickNodeProvider } from './web3_provider_quicknode.js'; + +export * from './types.js'; +export * from './web3_provider_quicknode.js'; +export * from './web3_provider.js'; + +// default providers +export const mainnet = new QuickNodeProvider(); \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/types.ts b/packages/web3-rpc-providers/src/types.ts new file mode 100644 index 00000000000..9da4c1dbfe7 --- /dev/null +++ b/packages/web3-rpc-providers/src/types.ts @@ -0,0 +1,44 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +export enum Transport { + HTTPS = "https", + WebSocket = "wss" +}; + +export enum Network { + ETH_MAINNET = "eth_mainnet", + ETH_GOERLI = "eth_goerli", + ETH_SEPOLIA = "eth_sepolia", + ETH_HOLESKY = "eth_holesky", + + POLYGON_MAINNET= "polygon_mainnet", + POLYGON_MUMBAI= "polygon_mumbai", + POLYGON_AMONY= "polygon_amony", + + ARBITRUM_MAINNET = "arbitrum_mainnet", + ARBITRUM_SEPOLIA = "arbitrum_sepolia", + + BASE_MAINNET = "base_mainnet", + BASE_SEPOLIA = "base_sepolia", + + OPTIMISM_MAINNET = "optimism_mainnet", + OPTIMISM_SEPOLIA = "optimism_sepolia", + + BNB_MAINNET = "bnb_mainnet", + BNB_TESTNET = "bnb_testnet" +}; \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/web3_provider.ts b/packages/web3-rpc-providers/src/web3_provider.ts new file mode 100644 index 00000000000..2bba9a7b880 --- /dev/null +++ b/packages/web3-rpc-providers/src/web3_provider.ts @@ -0,0 +1,135 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import HttpProvider from "web3-providers-http"; +import WebSocketProvider from "web3-providers-ws"; +import { + EthExecutionAPI, JsonRpcResult, ProviderConnectInfo, ProviderMessage, + ProviderRpcError, Web3APIMethod, Web3APIPayload, Web3APIReturnType, Web3APISpec, Web3BaseProvider, + Web3Eip1193ProviderEventCallback, + Web3ProviderEventCallback, + Web3ProviderMessageEventCallback, + Web3ProviderStatus +} from "web3-types"; +import { Eip1193Provider } from "web3-utils"; +import { Transport, Network } from "./types.js"; + +/* +This class can be used to create new providers only when there is custom logic required in each Request method like +checking specific HTTP status codes and performing any action, throwing new error types or setting additional HTTP headers in requests, or even modifying requests. + +Another simpler approach can be a function simply returning URL strings instead of using the following class in case if +no additional logic implementation is required in the provider. +*/ + +export abstract class Web3ExternalProvider < +API extends Web3APISpec = EthExecutionAPI, +> extends Eip1193Provider { + + public provider!: Web3BaseProvider; + public readonly transport: Transport; + + public abstract getRPCURL(network: Network,transport: Transport,token: string, host: string): string; + + public constructor( + network: Network, + transport: Transport, + token: string, + host: string) { + + super(); + + this.transport = transport; + if (transport === Transport.HTTPS) { + this.provider = new HttpProvider(this.getRPCURL(network, transport, token, host)); + } + else if (transport === Transport.WebSocket) { + this.provider = new WebSocketProvider(this.getRPCURL(network, transport, token, host)); + } + } + + public async request< + Method extends Web3APIMethod, + ResultType = Web3APIReturnType, + >( + payload: Web3APIPayload, + requestOptions?: RequestInit, + ): Promise { + + if (this.transport === Transport.HTTPS) { + return ( (this.provider as HttpProvider).request(payload, requestOptions)) as unknown as Promise; + } + + return ( (this.provider as WebSocketProvider).request(payload)) as unknown as Promise; + + } + + public getStatus(): Web3ProviderStatus { + return this.provider.getStatus(); + } + public supportsSubscriptions(): boolean { + return this.provider.supportsSubscriptions(); + } + public once(type: "disconnect", listener: Web3Eip1193ProviderEventCallback): void; + public once(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderEventCallback): void; + public once(type: "connect", listener: Web3Eip1193ProviderEventCallback): void; + public once(type: "chainChanged", listener: Web3Eip1193ProviderEventCallback): void; + public once(type: "accountsChanged", listener: Web3Eip1193ProviderEventCallback): void; + public once(_type: string, _listener: unknown): void { + if (this.provider?.once) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.provider.once(_type, _listener as any); + } + public removeAllListeners?(_type: string): void { + if (this.provider?.removeAllListeners) + this.provider.removeAllListeners(_type); + } + public connect(): void { + if (this.provider?.connect) + this.provider.connect(); + } + public disconnect(_code?: number | undefined, _data?: string | undefined): void { + if (this.provider?.disconnect) + this.provider.disconnect(_code, _data); + } + public reset(): void { + if (this.provider?.reset) + this.provider.reset(); + } + + public on(type: "disconnect", listener: Web3Eip1193ProviderEventCallback): void; + public on(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderMessageEventCallback): void; + public on(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderMessageEventCallback): void; + public on(type: "connect", listener: Web3Eip1193ProviderEventCallback): void; + public on(type: "chainChanged", listener: Web3Eip1193ProviderEventCallback): void; + public on(type: "accountsChanged", listener: Web3Eip1193ProviderEventCallback): void; + public on(_type: unknown, _listener: unknown): void { + if (this.provider) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.provider.on(_type as any, _listener as any); + } + public removeListener(type: "disconnect", listener: Web3Eip1193ProviderEventCallback): void; + public removeListener(type: string, listener: Web3Eip1193ProviderEventCallback | Web3ProviderEventCallback): void; + public removeListener(type: "connect", listener: Web3Eip1193ProviderEventCallback): void; + public removeListener(type: "chainChanged", listener: Web3Eip1193ProviderEventCallback): void; + public removeListener(type: "accountsChanged", listener: Web3Eip1193ProviderEventCallback): void; + public removeListener(_type: unknown, _listener: unknown): void { + if (this.provider) + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + this.provider.removeListener(_type as any, _listener as any); + } +} \ No newline at end of file diff --git a/packages/web3-rpc-providers/src/web3_provider_quicknode.ts b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts new file mode 100644 index 00000000000..a1b66880110 --- /dev/null +++ b/packages/web3-rpc-providers/src/web3_provider_quicknode.ts @@ -0,0 +1,91 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { Transport, Network } from "./types.js"; +import { Web3ExternalProvider } from "./web3_provider.js"; + +const isValid = (str: string) => str !== undefined && str.trim().length > 0; + +export class QuickNodeProvider extends Web3ExternalProvider { + + public constructor( + network: Network = Network.ETH_MAINNET, + transport: Transport = Transport.HTTPS, + token = "", + host = "") { + + super(network, transport, token, host); + + } + + // eslint-disable-next-line class-methods-use-this + public getRPCURL(network: Network, + transport: Transport, + _token: string, + _host: string) { + + let host = ""; + let token = ""; + + switch (network) { + case Network.ETH_MAINNET: + host = isValid(_host) ? _host : "powerful-holy-bush.quiknode.pro"; + token = isValid(_token) ? _token : "3240624a343867035925ff7561eb60dfdba2a668"; + break; + case Network.ETH_SEPOLIA: + host = isValid(_host) ? _host : "dimensional-fabled-glitter.ethereum-sepolia.quiknode.pro"; + token = isValid(_token) ? _token : "382a3b5a4b938f2d6e8686c19af4b22921fde2cd"; + break + case Network.ETH_HOLESKY: + host = isValid(_host) ? _host : "yolo-morning-card.ethereum-holesky.quiknode.pro"; + token = isValid(_token) ? _token : "481ebe70638c4dcf176af617a16d02ab866b9af9"; + break; + + case Network.ARBITRUM_MAINNET: + host = isValid(_host) ? _host : "autumn-divine-dinghy.arbitrum-mainnet.quiknode.pro"; + token = isValid(_token) ? _token : "a5d7bfbf60b5ae9ce3628e53d69ef50d529e9a8c"; + break; + case Network.ARBITRUM_SEPOLIA: + host = isValid(_host) ? _host : "few-patient-pond.arbitrum-sepolia.quiknode.pro"; + token = isValid(_token) ? _token : "3be985450970628c860b959c65cd2642dcafe53c"; + break; + + case Network.BNB_MAINNET: + host = isValid(_host) ? _host : "purple-empty-reel.bsc.quiknode.pro"; + token = isValid(_token) ? _token : "ebf6c532961e21f092ff2facce1ec4c89c540158"; + break; + case Network.BNB_TESTNET: + host = isValid(_host) ? _host : "floral-rough-scion.bsc-testnet.quiknode.pro"; + token = isValid(_token) ? _token : "5b297e5acff5f81f4c37ebf6f235f7299b6f9d28"; + break; + + case Network.POLYGON_MAINNET: + host = isValid(_host) ? _host : "small-chaotic-moon.matic.quiknode.pro"; + token = isValid(_token) ? _token : "847569f8a017e84d985e10d0f44365d965a951f1"; + break; + case Network.POLYGON_AMONY: + host = isValid(_host) ? _host : "prettiest-side-shape.matic-amoy.quiknode.pro"; + token = isValid(_token) ? _token : "79a9476eea661d4f82de614db1d8a895b14b881c"; + break; + default: + throw new Error("Network info not avalible."); + } + + return `${transport}://${host}/${token}`; + } +} + diff --git a/packages/web3-rpc-providers/test/.eslintrc.js b/packages/web3-rpc-providers/test/.eslintrc.js new file mode 100644 index 00000000000..a98dfb6d823 --- /dev/null +++ b/packages/web3-rpc-providers/test/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: '../../../.eslintrc.test.js', + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, +}; diff --git a/packages/web3-rpc-providers/test/config/jest.config.js b/packages/web3-rpc-providers/test/config/jest.config.js new file mode 120000 index 00000000000..b875b48129d --- /dev/null +++ b/packages/web3-rpc-providers/test/config/jest.config.js @@ -0,0 +1 @@ +../../../../templates/jest.config.js.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/test/config/setup.js b/packages/web3-rpc-providers/test/config/setup.js new file mode 100644 index 00000000000..0b6b9109ce0 --- /dev/null +++ b/packages/web3-rpc-providers/test/config/setup.js @@ -0,0 +1,24 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +// Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules +// eslint-disable-next-line @typescript-eslint/no-require-imports +require('jest-extended'); + +// @todo extend jest to have "toHaveBeenCalledOnceWith" matcher. + +process.env.NODE_ENV = 'test'; diff --git a/packages/web3-rpc-providers/test/integration/jest.config.js b/packages/web3-rpc-providers/test/integration/jest.config.js new file mode 100644 index 00000000000..1d95890206a --- /dev/null +++ b/packages/web3-rpc-providers/test/integration/jest.config.js @@ -0,0 +1,33 @@ +'use strict'; + +const base = require('../config/jest.config'); + +module.exports = { + ...base, + setupFilesAfterEnv: ['/test/integration/setup.js'], + testMatch: ['/test/integration/**/*.(spec|test).(js|ts)'], + /** + * restoreMocks [boolean] + * + * Default: false + * + * Automatically restore mock state between every test. + * Equivalent to calling jest.restoreAllMocks() between each test. + * This will lead to any mocks having their fake implementations removed + * and restores their initial implementation. + */ + restoreMocks: true, + + /** + * resetModules [boolean] + * + * Default: false + * + * By default, each test file gets its own independent module registry. + * Enabling resetModules goes a step further and resets the module registry before running each individual test. + * This is useful to isolate modules for every test so that local module state doesn't conflict between tests. + * This can be done programmatically using jest.resetModules(). + */ + resetModules: true, + coverageDirectory: '.coverage/integration', +}; diff --git a/packages/web3-rpc-providers/test/integration/setup.js b/packages/web3-rpc-providers/test/integration/setup.js new file mode 100644 index 00000000000..5be1bccf7cc --- /dev/null +++ b/packages/web3-rpc-providers/test/integration/setup.js @@ -0,0 +1,24 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +// Have to use `require` because of Jest issue https://jestjs.io/docs/ecmascript-modules +// eslint-disable-next-line @typescript-eslint/no-require-imports +require('../config/setup'); + +const jestTimeout = 15000; + +jest.setTimeout(jestTimeout); diff --git a/packages/web3-rpc-providers/test/tsconfig.json b/packages/web3-rpc-providers/test/tsconfig.json new file mode 120000 index 00000000000..c73c54e77b4 --- /dev/null +++ b/packages/web3-rpc-providers/test/tsconfig.json @@ -0,0 +1 @@ +../../../templates/test/tsconfig.json.tmpl \ No newline at end of file diff --git a/packages/web3-rpc-providers/test/unit/constructor.test.ts b/packages/web3-rpc-providers/test/unit/constructor.test.ts new file mode 100644 index 00000000000..eb64b29163a --- /dev/null +++ b/packages/web3-rpc-providers/test/unit/constructor.test.ts @@ -0,0 +1,62 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +/* eslint-disable max-classes-per-file */ + +import HttpProvider from 'web3-providers-http'; +import WebSocketProvider from 'web3-providers-ws'; +import { Web3ExternalProvider } from '../../src/web3_provider'; +import { Network, Transport } from '../../src/types'; + +class MockWeb3ExternalProviderA extends Web3ExternalProvider { + public constructor(network: Network, transport: Transport, token: string){ + super(network, transport, token, ""); + } + // eslint-disable-next-line class-methods-use-this + public getRPCURL(_network: Network, _transport: Transport, _token: string, _host=""): string { + let transport = ""; + if (_transport === Transport.HTTPS) + transport = "http://"; + else if (_transport === Transport.WebSocket) + transport = "wss://"; + + return `${transport}example.com/`; + } +} + +describe('Web3ExternalProvider', () => { + it('should initialize the provider correctly', () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + const token = 'your-token'; + + const provider = new MockWeb3ExternalProviderA(network, transport, token); + + expect(provider.provider).toBeInstanceOf(HttpProvider); + }); + + it('should initialize the provider with WebSocketProvider for WebSocket transport', () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.WebSocket; + const token = 'your-token'; + + const provider = new MockWeb3ExternalProviderA(network, transport, token); + + expect(provider.provider).toBeInstanceOf(WebSocketProvider); + }); + +}); +/* eslint-enable max-classes-per-file */ \ No newline at end of file diff --git a/packages/web3-rpc-providers/test/unit/jest.config.js b/packages/web3-rpc-providers/test/unit/jest.config.js new file mode 100644 index 00000000000..ceac341e332 --- /dev/null +++ b/packages/web3-rpc-providers/test/unit/jest.config.js @@ -0,0 +1,9 @@ +const base = require('../config/jest.config'); + +module.exports = { + ...base, + testMatch: ['/test/unit/**/*.(spec|test).(js|ts)'], + + coverageDirectory: '.coverage/unit', + collectCoverageFrom: ['src/**'], +}; diff --git a/packages/web3-rpc-providers/test/unit/request.test.ts b/packages/web3-rpc-providers/test/unit/request.test.ts new file mode 100644 index 00000000000..ccbaa0f7cc7 --- /dev/null +++ b/packages/web3-rpc-providers/test/unit/request.test.ts @@ -0,0 +1,81 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3APIPayload, EthExecutionAPI, Web3APIMethod } from "web3-types"; +import { Network, Transport } from "../../src/types"; +import { Web3ExternalProvider } from "../../src/web3_provider"; + +jest.mock('web3-providers-ws', () => { + return { + __esModule: true, + default: jest.fn().mockImplementation(() => ({ + request: jest.fn().mockResolvedValue({ result: 'mock-result' }), + })), + }; +}); + +class MockWeb3ExternalProvider extends Web3ExternalProvider { + public constructor(network: Network, transport: Transport, token: string){ + super(network, transport, token, ""); + } + // eslint-disable-next-line class-methods-use-this + public getRPCURL(_network: Network, _transport: Transport, _token: string): string { + return 'https://example.com/'; + } + } + +describe('Web3ExternalProvider', () => { + it('should make a request using the HTTPS provider', async () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.HTTPS; + const token = 'your-token'; + + const mockHttpProvider = { + request: jest.fn(), + }; + + const mockResponse = { result: 'mock-result' }; + mockHttpProvider.request.mockResolvedValue(mockResponse); + + const provider = new MockWeb3ExternalProvider(network, transport, token); + (provider as any).provider = mockHttpProvider; + + const payload: Web3APIPayload> = { + method: 'eth_getBalance', + params: ['0x0123456789012345678901234567890123456789', 'latest'], + }; + + const result = await provider.request(payload); + expect(result).toEqual(mockResponse); + }); + + it('should make a request using the WebSocket provider', async () => { + const network: Network = Network.ETH_MAINNET; + const transport: Transport = Transport.WebSocket; + const token = 'your-token'; + + const provider = new MockWeb3ExternalProvider(network, transport, token); + (provider as any).getRPCURL = jest.fn().mockReturnValue('ws://mock-rpc-url.com'); + + const payload: Web3APIPayload> = { + method: 'eth_getBalance', + params: ['0x0123456789012345678901234567890123456789', 'latest'], + }; + + const result = await provider.request(payload); + expect(result).toEqual({ result: 'mock-result' }); + }); +}); \ No newline at end of file diff --git a/packages/web3-rpc-providers/tsconfig.cjs.json b/packages/web3-rpc-providers/tsconfig.cjs.json new file mode 120000 index 00000000000..f8b17044cd5 --- /dev/null +++ b/packages/web3-rpc-providers/tsconfig.cjs.json @@ -0,0 +1 @@ +../../config/tsconfig.cjs.json \ No newline at end of file diff --git a/packages/web3-rpc-providers/tsconfig.esm.json b/packages/web3-rpc-providers/tsconfig.esm.json new file mode 120000 index 00000000000..f5fab722b38 --- /dev/null +++ b/packages/web3-rpc-providers/tsconfig.esm.json @@ -0,0 +1 @@ +../../config/tsconfig.esm.json \ No newline at end of file diff --git a/packages/web3-rpc-providers/tsconfig.types.json b/packages/web3-rpc-providers/tsconfig.types.json new file mode 120000 index 00000000000..c67a7816f18 --- /dev/null +++ b/packages/web3-rpc-providers/tsconfig.types.json @@ -0,0 +1 @@ +../../config/tsconfig.types.json \ No newline at end of file diff --git a/packages/web3-rpc-providers/tsdoc.json b/packages/web3-rpc-providers/tsdoc.json new file mode 100644 index 00000000000..776fc76a3d3 --- /dev/null +++ b/packages/web3-rpc-providers/tsdoc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + "extends": ["../../tsdoc.json"] +} diff --git a/packages/web3/package.json b/packages/web3/package.json index 668d77e26ff..7627ff6826b 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -101,6 +101,7 @@ "web3-rpc-methods": "^1.3.0", "web3-types": "^1.6.0", "web3-utils": "^4.3.0", - "web3-validator": "^2.0.6" + "web3-validator": "^2.0.6", + "web3-rpc-providers": "^0.1.0" } } diff --git a/packages/web3/src/web3.ts b/packages/web3/src/web3.ts index 0fda2c10521..a3b6b462842 100644 --- a/packages/web3/src/web3.ts +++ b/packages/web3/src/web3.ts @@ -30,6 +30,7 @@ import { Personal } from 'web3-eth-personal'; import { Net } from 'web3-net'; import * as utils from 'web3-utils'; import { isNullish, isDataFormat, isContractInitOptions } from 'web3-utils'; +import { mainnet } from 'web3-rpc-providers'; import { Address, ContractAbi, @@ -67,10 +68,10 @@ export class Web3< public eth: Web3EthInterface; public constructor( - providerOrContext?: + providerOrContext: | string | SupportedProviders - | Web3ContextInitOptions, + | Web3ContextInitOptions = mainnet, ) { if ( isNullish(providerOrContext) || diff --git a/packages/web3/test/integration/web3.test.ts b/packages/web3/test/integration/web3.test.ts index 18a49dd0fcc..37587954bb0 100644 --- a/packages/web3/test/integration/web3.test.ts +++ b/packages/web3/test/integration/web3.test.ts @@ -124,13 +124,13 @@ describe('Web3 instance', () => { expect(typeof web3Instance.eth.currentProvider?.disconnect).toBe('function'); }); - it('should be able use "utils" without provider', () => { + it('should be able use "utils"', () => { web3 = new Web3(); expect(web3.utils.hexToNumber('0x5')).toBe(5); }); - it('should be able use "abi" without provider', () => { + it('should be able use "abi"', () => { web3 = new Web3(); const validData = validEncodeParametersData[0]; @@ -141,12 +141,6 @@ describe('Web3 instance', () => { expect(encodedParameters).toEqual(validData.output); }); - it('should throw error when we make a request when provider not available', async () => { - web3 = new Web3(); - - await expect(web3.eth.getChainId()).rejects.toThrow('Provider not available'); - }); - describeIf(isHttp)('Create Web3 class instance with http string providers', () => { it('should create instance with string provider', () => { web3 = new Web3(provider); diff --git a/packages/web3/test/integration/web3RPCProviders.test.ts b/packages/web3/test/integration/web3RPCProviders.test.ts new file mode 100644 index 00000000000..24bc312610d --- /dev/null +++ b/packages/web3/test/integration/web3RPCProviders.test.ts @@ -0,0 +1,61 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { mainnet , Network, QuickNodeProvider, Transport } from "web3-rpc-providers"; +import { Web3 } from '../../src/index'; + +describe('Web3 RPC Provider Integration tests', () => { + const transports = Object.values(Transport); + const networks = [Network.ETH_MAINNET, Network.ETH_HOLESKY, Network.ETH_SEPOLIA, + Network.ARBITRUM_MAINNET, Network.ARBITRUM_SEPOLIA, + Network.BNB_MAINNET, Network.BNB_TESTNET, + Network.POLYGON_MAINNET, Network.POLYGON_AMONY]; + + transports.forEach((transport) => { + networks.forEach((network) => { + it(`QuickNodeProvider should work with ${transport} transport and ${network} network`, async () => { + + const provider = new QuickNodeProvider(network, transport); + const web3 = new Web3(provider); + const result = await web3.eth.getBlockNumber() + + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + + if (transport === Transport.WebSocket) { + web3.provider?.disconnect(); + } + + }); + }); + }); + it(`should work with mainnet provider`, async () => { + const web3 = new Web3(mainnet); + const result = await web3.eth.getBlockNumber() + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + + }); + + it(`should work with default provider`, async () => { + const web3 = new Web3(); + const result = await web3.eth.getBlockNumber() + expect(typeof result).toBe('bigint'); + expect(result > 0).toBe(true); + + }); +}); \ No newline at end of file diff --git a/packages/web3/test/unit/web3.test.ts b/packages/web3/test/unit/web3.test.ts index 3d520f38e36..3cd00a9e718 100644 --- a/packages/web3/test/unit/web3.test.ts +++ b/packages/web3/test/unit/web3.test.ts @@ -21,9 +21,9 @@ import { Web3 } from '../../src/web3'; describe('Web3 object', () => { it('should be able to set and read web3 providers', () => { - const web3NoProvider = new Web3(); + const web3NoProvider = new Web3(""); expect(web3NoProvider).toBeTruthy(); - expect(web3NoProvider.provider).toBeUndefined(); + expect(web3NoProvider.provider).toBe(""); const web3 = new Web3('http://somenode'); expect(web3).toBeTruthy(); diff --git a/templates/.eslintignore.tmpl b/templates/.eslintignore.tmpl index ffb881be6b5..c2d4ae29304 100644 --- a/templates/.eslintignore.tmpl +++ b/templates/.eslintignore.tmpl @@ -1,9 +1,10 @@ dist lib +hardhat.config.js jest.config.js -.eslintrc.js cypress cypress.config.js +.eslintrc.js src/common/chains/** src/common/eips/** -src/common/hardforks/** \ No newline at end of file +src/common/hardforks/** From 683be62b176e87230c125c7aa52dd25edee80ae7 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 28 May 2024 05:49:44 -0700 Subject: [PATCH 06/25] fix(docs): quickstart (#7062) --- .../docs/guides/getting_started/quickstart.md | 72 +++++++++++-------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/docs/docs/guides/getting_started/quickstart.md b/docs/docs/guides/getting_started/quickstart.md index d023e01bb9f..c1db2a9fdc8 100644 --- a/docs/docs/guides/getting_started/quickstart.md +++ b/docs/docs/guides/getting_started/quickstart.md @@ -5,6 +5,7 @@ sidebar_label: Quickstart # Quickstart +Use the live code editor to try Web3.js in your browser now! Keep reading to learn how to use Web3.js in a local development environment. ## Live code editor @@ -12,29 +13,29 @@ sidebar_label: Quickstart ## Installation -If NPM is being used as package manager, use the following for installing the web3.js library. +If NPM is being used as package manager, install Web3.js with the following command: ``` npm i web3 ``` -For installing using yarn package manager: +For projects using Yarn as a package manager, use: ``` yarn add web3 ``` -Note: Installing web3.js in this way will bring in all web3.js sub-packages, if you only need specific packages, it is recommended to install the specific required packages (e.g, if you want the contract package `npm i web3-eth-contract` instead) +Note: Installing Web3.js in this way will bring in all Web3.js sub-[packages](/#packages). If you only need specific packages, it is recommended to install them individually (e.g, if you want the [Contract](/libdocs/Contract) package, use `npm i web3-eth-contract` instead) ## Importing Web3.js -Web3.js v4 supports both CJS ( CommonJS ) and native ESM module imports. For importing the main Web3 class in CJS you can use: +Web3.js v4 supports both CommonJS (CJS) and native ECMAScript module (ESM) imports. For importing the main Web3 class in CJS, use: ``` js const { Web3 } = require('web3'); ``` -and for ESM style imports, you can use: +For ESM-style imports, use: ``` ts import { Web3 } from 'web3'; @@ -42,11 +43,9 @@ import { Web3 } from 'web3'; ## Initialize `Web3` with a provider -Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) so any EIP-1193 provider can be injected in web3.js . There are HTTP, WebSocket and IPC providers also available as web3.js packages for using. +[Providers](/guides/web3_providers_guide/) are objects that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. -:::warning -You must initialize the `Web3` object with a provider, otherwise, you won't be able to fully use web3.js functionalities. Here is an example of creating a `web3` instance with an HTTP provider: -::: +Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193), the Ethereum Provider JavaScript API, so any EIP-1193 provider can be used to initialize the `Web3` object. ``` ts import { Web3 } from 'web3'; @@ -62,7 +61,7 @@ web3.eth.getBlockNumber().then(console.log); ``` ## Querying the blockchain -After instantiating the `web3` instance with a `new Web3 provider`, we can access the `web3.eth` package to fetch data from the blockchain: +After instantiating the `Web3` instance with a provider, the [`web3-eth`](/libdocs/Web3Eth) package can be used to fetch data from the Ethereum network: ```ts // get the balance of an address @@ -88,11 +87,13 @@ await web3.eth.getGasPrice(); ## Setting up a wallet -If you want to write data/interact with contracts or send transactions on the blockchain, you must have an account with funds to cover the gas fees. +To send transactions to the Ethereum network (e.g. [transferring ETH](/guides/getting_started/quickstart#transfer-eth) or [interacting with smart contracts](/guides/getting_started/quickstart#interact-with-smart-contracts)), it's necessary to use an [account](https://ethereum.org/en/developers/docs/accounts/) with funds to cover [gas fees](https://ethereum.org/en/developers/docs/gas/). -The object `Wallet` is an array of accounts, it will allow you to hold several accounts from which you can send transactions `web3.eth.sendTransaction` or interact with contract objects `web3.eth.contract.methods.contractfunction().send()`, when you perform these actions, the `Wallet` object uses the account/s it holds to send the transactions. +The [`Wallet`](/api/web3-eth-accounts/class/Wallet) object is designed to manage a set of accounts that can be used to send transactions with [`web3.eth.sendTransaction`](/api/web3/class/Web3Eth#sendTransaction) or [`web3.eth.contract.methods.contractfunction().send()`](/api/web3-eth-contract/class/Contract). -### Create random wallet +### Create a random account + +Using the `Wallet` to create a random account is a good way to accelerate the development process, but it's not suitable for mainnet or production uses, since random accounts will not have funds to cover gas fees. Use the [`Wallet.create`](/api/web3-eth-accounts/class/Wallet#create) method to create a random account. ```ts //create random wallet with 1 account @@ -118,7 +119,13 @@ Wallet(1) */ ``` -### Add a private key to create a wallet +### Add an account from a private key + +Use the [`Wallet.add`](/api/web3-eth-accounts/class/Wallet#add) method to use a private key to add an existing account to a wallet. + +:::warning +Private keys are sensitive data and should be treated as such. Make sure that private keys are kept private, which includes making sure they are not committed to code repositories. +::: ```ts //the private key must start with the '0x' prefix @@ -131,9 +138,11 @@ console.log(account[0].privateKey); //↳ 0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec ``` -### Send transactions +### Transfer ETH + +This is an example of using a private key to add an account to a wallet, and then using that account to transfer ETH: -```ts title='Sending value' +```ts //add an account to a wallet const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); @@ -155,15 +164,18 @@ console.log('Tx hash:', txReceipt.transactionHash) ## Interact with smart contracts +[Smart contracts](https://ethereum.org/en/developers/docs/smart-contracts/) are programs that run on the Ethereum network. Keep reading to learn how to use Web3.js to interact with smart contracts. + ### Instantiate a contract -The first step to interact with a contract is to instantiate the contract, for which we will need the ABI and the address of the contract +The first step to interacting with a smart contract is to instantiate it, which requires the [ABI](https://docs.soliditylang.org/en/develop/abi-spec.html) and address of the smart contract. The following examples demonstrates instantiating the [Uniswap](https://uniswap.org/) token smart contract: ```ts -//Uniswap token address in mainnet +//Uniswap token smart contract address (mainnet) const address = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984' //you can find the complete ABI in etherscan.io +//https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code const ABI = [ { @@ -178,11 +190,13 @@ const ABI = }, ]; -//instantiate the contract +//instantiate the smart contract const uniswapToken = new web3.eth.Contract(abi, address); ``` -### Read-methods +### Read methods + +Since reading data from a smart contract does not consume any gas, it's not necessary to use an account to do so. Here are some examples of reading data from the Uniswap token smart contract: ```ts //make the call to the contract @@ -196,13 +210,11 @@ const totalSupply = await uniswapToken.methods.totalSupply().call(); console.log('Uniswap Total supply:', totalSupply); // ↳ Uniswap Total Supply: 1000000000000000000000000000n - -//use web3 utils to format the units -console.log(web3.utils.fromWei(totalSupply, 'ether')) -// ↳ 1000000000 ``` -### Writing-methods +### Write methods + +Writing data to a smart contract consumes gas and requires the use of an account with funds. The following example demonstrates such an interaction: ```ts //address to send the token @@ -220,6 +232,8 @@ console.log('Tx hash:',txReceipt.transactionHash); ### Query past events +Smart contracts emit [events](https://ethereum.org/en/developers/docs/smart-contracts/anatomy/#events-and-logs) to communicate important interactions. This example demonstrates how to query the Uniswap token smart contract for all `Transfer` events that occurred after a certain block number: + ```ts //get past `Transfer` events from block 18850576 const eventTransfer = await uniswapToken.getPastEvents('Transfer', { fromBlock: 18850576 }); @@ -229,10 +243,12 @@ console.log(eventTransfer); //you can only query logs from the previous 100_000 blocks ``` -### Listening to live events +### Subscribing to events -:::warning -You MUST initialize the `Web3 provider` with a WebSocket endpoint to subscribe to live events +Web3.js allows user to subscribe to events for real-time notification of important contract interactions. Here is an example of creating a subscription to the Uniswap token's `Transfer` event: + +:::note +You MUST initialize the `Web3` object with a [WebSocket](/guides/web3_providers_guide/#websocket-provider) provider to subscribe to live events. ::: ```ts From 70846654d00797a0eb1f23b33710e85a6cf5aacc Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Wed, 29 May 2024 10:54:49 -0400 Subject: [PATCH 07/25] add .snyk file (#7064) --- .snyk | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .snyk diff --git a/.snyk b/.snyk new file mode 100644 index 00000000000..cb9591ea045 --- /dev/null +++ b/.snyk @@ -0,0 +1,51 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-WEB3-174533: + - '*': + reason: Ignore test issue + expires: 3024-06-26T17:16:53.075Z + created: 2024-05-27T17:16:53.080Z + SNYK-JS-BRACES-6838727: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:07.153Z + created: 2024-05-27T17:29:07.159Z + SNYK-JS-EXPRESS-6474509: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:31.142Z + created: 2024-05-27T17:29:31.149Z + SNYK-JS-INFLIGHT-6095116: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:51.622Z + created: 2024-05-27T17:29:51.628Z + SNYK-JS-MICROMATCH-6838728: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:30:47.237Z + created: 2024-05-27T17:30:47.240Z + SNYK-JS-SERIALIZEJAVASCRIPT-6147607: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:31:06.652Z + created: 2024-05-27T17:31:06.656Z + SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T20:52:00.793Z + created: 2024-05-27T20:52:00.797Z + SNYK-JS-JSON5-3182856: + - '*': + reason: Eslint problem + expires: 3024-06-26T20:53:53.640Z + created: 2024-05-27T20:53:53.644Z + SNYK-JS-SEMVER-3247795: + - '*': + reason: Eslint problem + expires: 3024-06-26T20:54:20.755Z + created: 2024-05-27T20:54:20.759Z + +patch: {} From f687df68be35de271e911f39cddf70abe58ec1f8 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Wed, 29 May 2024 16:07:06 -0400 Subject: [PATCH 08/25] Use .snyk file for all projects (#7071) --- docs/.snyk | 36 ++++++++++++++++++++ packages/web3/.snyk | 21 ++++++++++++ .snyk => tools/eslint-config-base-web3/.snyk | 12 +------ 3 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 docs/.snyk create mode 100644 packages/web3/.snyk rename .snyk => tools/eslint-config-base-web3/.snyk (78%) diff --git a/docs/.snyk b/docs/.snyk new file mode 100644 index 00000000000..b29b615196e --- /dev/null +++ b/docs/.snyk @@ -0,0 +1,36 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-BRACES-6838727: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:07.153Z + created: 2024-05-27T17:29:07.159Z + SNYK-JS-EXPRESS-6474509: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:31.142Z + created: 2024-05-27T17:29:31.149Z + SNYK-JS-INFLIGHT-6095116: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:29:51.622Z + created: 2024-05-27T17:29:51.628Z + SNYK-JS-MICROMATCH-6838728: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:30:47.237Z + created: 2024-05-27T17:30:47.240Z + SNYK-JS-SERIALIZEJAVASCRIPT-6147607: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T17:31:06.652Z + created: 2024-05-27T17:31:06.656Z + SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: + - '*': + reason: Docusaurus issue + expires: 3024-06-26T20:52:00.793Z + created: 2024-05-27T20:52:00.797Z + +patch: {} diff --git a/packages/web3/.snyk b/packages/web3/.snyk new file mode 100644 index 00000000000..5b289bc1640 --- /dev/null +++ b/packages/web3/.snyk @@ -0,0 +1,21 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-WEB3-174533: + - '*': + reason: Ignore test issue + expires: 3024-06-26T17:16:53.075Z + created: 2024-05-27T17:16:53.080Z + SNYK-JS-JSON5-3182856: + - '*': + reason: Eslint problem + expires: 3024-06-26T20:53:53.640Z + created: 2024-05-27T20:53:53.644Z + SNYK-JS-SEMVER-3247795: + - '*': + reason: Eslint problem + expires: 3024-06-26T20:54:20.755Z + created: 2024-05-27T20:54:20.759Z + +patch: {} diff --git a/.snyk b/tools/eslint-config-base-web3/.snyk similarity index 78% rename from .snyk rename to tools/eslint-config-base-web3/.snyk index cb9591ea045..f0ce4e19c9c 100644 --- a/.snyk +++ b/tools/eslint-config-base-web3/.snyk @@ -2,11 +2,6 @@ version: v1.25.0 # ignores vulnerabilities until expiry date; change duration by modifying expiry date ignore: - SNYK-JS-WEB3-174533: - - '*': - reason: Ignore test issue - expires: 3024-06-26T17:16:53.075Z - created: 2024-05-27T17:16:53.080Z SNYK-JS-BRACES-6838727: - '*': reason: Docusaurus issue @@ -24,14 +19,9 @@ ignore: created: 2024-05-27T17:29:51.628Z SNYK-JS-MICROMATCH-6838728: - '*': - reason: Docusaurus issue + reason: Eslint issue expires: 3024-06-26T17:30:47.237Z created: 2024-05-27T17:30:47.240Z - SNYK-JS-SERIALIZEJAVASCRIPT-6147607: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:31:06.652Z - created: 2024-05-27T17:31:06.656Z SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: - '*': reason: Docusaurus issue From b63af9f10c57b9b0dfc920f664ea3123b9ed1c06 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Thu, 30 May 2024 06:11:17 -0700 Subject: [PATCH 09/25] fix(docs): sidebar (#7063) * Move MetaMask guide to Accounts section * Reorganize sidebar * Fix broken link --- docs/docs/guides/advanced/_category_.yml | 2 +- docs/docs/guides/events_subscriptions/_category_.yml | 2 +- docs/docs/guides/feedback/index.md | 2 +- docs/docs/guides/hardhat_tutorial/_category_.yml | 2 +- docs/docs/guides/migration_from_other_libs/_category_.yml | 2 +- docs/docs/guides/resources_and_troubleshooting/index.md | 2 +- docs/docs/guides/smart_contracts/_category_.yml | 2 +- docs/docs/guides/wagmi_usage/_category_.yml | 2 +- docs/docs/guides/wallet/_category_.yml | 2 +- docs/docs/guides/{getting_started => wallet}/metamask.md | 2 +- docs/docs/guides/wallet/node_wallet.md | 2 +- docs/docs/guides/wallet/signing.md | 2 +- docs/docs/guides/wallet/transactions.md | 2 +- .../guides/{ => wallet}/web3_modal_guide/_category_.yml | 2 +- docs/docs/guides/{ => wallet}/web3_modal_guide/index.mdx | 8 ++++---- docs/docs/guides/{ => wallet}/web3_modal_guide/vue.md | 0 docs/docs/guides/web3_config/_category_.yml | 2 +- docs/docs/guides/web3_plugin_guide/_category_.yml | 2 +- docs/docs/guides/web3_providers_guide/_category_.yml | 2 +- docs/docs/guides/web3_upgrade_guide/_category_.yml | 2 +- 20 files changed, 22 insertions(+), 22 deletions(-) rename docs/docs/guides/{getting_started => wallet}/metamask.md (99%) rename docs/docs/guides/{ => wallet}/web3_modal_guide/_category_.yml (87%) rename docs/docs/guides/{ => wallet}/web3_modal_guide/index.mdx (97%) rename docs/docs/guides/{ => wallet}/web3_modal_guide/vue.md (100%) diff --git a/docs/docs/guides/advanced/_category_.yml b/docs/docs/guides/advanced/_category_.yml index 3131878f18e..c6ab4f48016 100644 --- a/docs/docs/guides/advanced/_category_.yml +++ b/docs/docs/guides/advanced/_category_.yml @@ -2,4 +2,4 @@ label: '🧠 Advanced' collapsible: true collapsed: true link: null -position: 15 \ No newline at end of file +position: 11 diff --git a/docs/docs/guides/events_subscriptions/_category_.yml b/docs/docs/guides/events_subscriptions/_category_.yml index 2f13d5222b4..9207b5b28c2 100644 --- a/docs/docs/guides/events_subscriptions/_category_.yml +++ b/docs/docs/guides/events_subscriptions/_category_.yml @@ -2,4 +2,4 @@ label: '🔔 Events subscription' collapsible: true collapsed: true link: null -position: 7 \ No newline at end of file +position: 5 diff --git a/docs/docs/guides/feedback/index.md b/docs/docs/guides/feedback/index.md index 0118436ec91..228003d5a6e 100644 --- a/docs/docs/guides/feedback/index.md +++ b/docs/docs/guides/feedback/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 18 +sidebar_position: 17 sidebar_label: 'ðŸ—£ï¸ Feedback' --- diff --git a/docs/docs/guides/hardhat_tutorial/_category_.yml b/docs/docs/guides/hardhat_tutorial/_category_.yml index 191ad0faa29..8493ca97d6e 100644 --- a/docs/docs/guides/hardhat_tutorial/_category_.yml +++ b/docs/docs/guides/hardhat_tutorial/_category_.yml @@ -2,4 +2,4 @@ label: 'â›‘ï¸ Hardhat Tutorial' collapsible: true collapsed: true link: null -position: 3 +position: 6 diff --git a/docs/docs/guides/migration_from_other_libs/_category_.yml b/docs/docs/guides/migration_from_other_libs/_category_.yml index 665581166bc..59fb5de8cdc 100644 --- a/docs/docs/guides/migration_from_other_libs/_category_.yml +++ b/docs/docs/guides/migration_from_other_libs/_category_.yml @@ -2,4 +2,4 @@ label: '🔄 Migration Guides' collapsible: true collapsed: true link: null -position: 12 \ No newline at end of file +position: 15 diff --git a/docs/docs/guides/resources_and_troubleshooting/index.md b/docs/docs/guides/resources_and_troubleshooting/index.md index 6426b99d8df..2dd82f1e5b6 100644 --- a/docs/docs/guides/resources_and_troubleshooting/index.md +++ b/docs/docs/guides/resources_and_troubleshooting/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 17 +sidebar_position: 16 sidebar_label: '📚 Resources & Troubleshooting' --- # Resources & Troubleshooting diff --git a/docs/docs/guides/smart_contracts/_category_.yml b/docs/docs/guides/smart_contracts/_category_.yml index fcbba9574a5..8a1d21c75b4 100644 --- a/docs/docs/guides/smart_contracts/_category_.yml +++ b/docs/docs/guides/smart_contracts/_category_.yml @@ -2,4 +2,4 @@ label: '📜 Smart Contracts' collapsible: true collapsed: true link: null -position: 6 \ No newline at end of file +position: 4 diff --git a/docs/docs/guides/wagmi_usage/_category_.yml b/docs/docs/guides/wagmi_usage/_category_.yml index 90b55da4312..ee90c923e38 100644 --- a/docs/docs/guides/wagmi_usage/_category_.yml +++ b/docs/docs/guides/wagmi_usage/_category_.yml @@ -2,4 +2,4 @@ label: '🔄 Wagmi usage' collapsible: true collapsed: true link: null -position: 13 +position: 14 diff --git a/docs/docs/guides/wallet/_category_.yml b/docs/docs/guides/wallet/_category_.yml index 6b079975e01..dde0bddd9ed 100644 --- a/docs/docs/guides/wallet/_category_.yml +++ b/docs/docs/guides/wallet/_category_.yml @@ -2,4 +2,4 @@ label: '🔑 Wallet and Accounts ' collapsible: true collapsed: true link: null -position: 5 \ No newline at end of file +position: 3 diff --git a/docs/docs/guides/getting_started/metamask.md b/docs/docs/guides/wallet/metamask.md similarity index 99% rename from docs/docs/guides/getting_started/metamask.md rename to docs/docs/guides/wallet/metamask.md index e40db544ac6..888f5890b1a 100644 --- a/docs/docs/guides/getting_started/metamask.md +++ b/docs/docs/guides/wallet/metamask.md @@ -1,6 +1,6 @@ --- sidebar_position: 4 -sidebar_label: Connecting to Metamask +sidebar_label: 'Tutorial: Connecting to Metamask' --- # Connecting to Metamask diff --git a/docs/docs/guides/wallet/node_wallet.md b/docs/docs/guides/wallet/node_wallet.md index a4adbbab987..7b70ed655a3 100644 --- a/docs/docs/guides/wallet/node_wallet.md +++ b/docs/docs/guides/wallet/node_wallet.md @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 8 sidebar_label: 'Tutorial: Node Wallet' --- diff --git a/docs/docs/guides/wallet/signing.md b/docs/docs/guides/wallet/signing.md index 88184c2a7fa..54b3779cd17 100644 --- a/docs/docs/guides/wallet/signing.md +++ b/docs/docs/guides/wallet/signing.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 6 sidebar_label: 'Tutorial: Signing operations' --- diff --git a/docs/docs/guides/wallet/transactions.md b/docs/docs/guides/wallet/transactions.md index 5129c5057a4..c86da4c9113 100644 --- a/docs/docs/guides/wallet/transactions.md +++ b/docs/docs/guides/wallet/transactions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 7 sidebar_label: 'Tutorial: Sending Transactions' --- diff --git a/docs/docs/guides/web3_modal_guide/_category_.yml b/docs/docs/guides/wallet/web3_modal_guide/_category_.yml similarity index 87% rename from docs/docs/guides/web3_modal_guide/_category_.yml rename to docs/docs/guides/wallet/web3_modal_guide/_category_.yml index 6744910f3b6..19d6fe3a639 100644 --- a/docs/docs/guides/web3_modal_guide/_category_.yml +++ b/docs/docs/guides/wallet/web3_modal_guide/_category_.yml @@ -2,4 +2,4 @@ label: '📱 WalletConnect Tutorial' collapsible: true collapsed: true link: null -position: 14 \ No newline at end of file +position: 5 diff --git a/docs/docs/guides/web3_modal_guide/index.mdx b/docs/docs/guides/wallet/web3_modal_guide/index.mdx similarity index 97% rename from docs/docs/guides/web3_modal_guide/index.mdx rename to docs/docs/guides/wallet/web3_modal_guide/index.mdx index a1bef97eb66..2d8b878196f 100644 --- a/docs/docs/guides/web3_modal_guide/index.mdx +++ b/docs/docs/guides/wallet/web3_modal_guide/index.mdx @@ -104,8 +104,8 @@ const USDTAddress = '0xdac17f958d2ee523a2206206994597c13d831ec7'; function Components() { const { isConnected } = useWeb3ModalAccount() const { walletProvider } = useWeb3ModalProvider() - const [USDTBalance, setUSDTBalance] = useState(0); - const [smartContractName, setSmartContractName] = useState(''); + const [USDTBalance, setUSDTBalance] = useState(0); + const [smartContractName, setSmartContractName] = useState(''); async function getContractInfo() { if (!isConnected) throw Error('not connected'); @@ -126,5 +126,5 @@ function Components() { ``` :::info -- To learn how to set up Web3modal with vue, click [here](/guides/web3_modal_guide/vue). -::: \ No newline at end of file +- To learn how to set up Web3modal with vue, click [here](/guides/wallet/web3_modal_guide/vue). +::: diff --git a/docs/docs/guides/web3_modal_guide/vue.md b/docs/docs/guides/wallet/web3_modal_guide/vue.md similarity index 100% rename from docs/docs/guides/web3_modal_guide/vue.md rename to docs/docs/guides/wallet/web3_modal_guide/vue.md diff --git a/docs/docs/guides/web3_config/_category_.yml b/docs/docs/guides/web3_config/_category_.yml index d1fd0583848..6070480ec67 100644 --- a/docs/docs/guides/web3_config/_category_.yml +++ b/docs/docs/guides/web3_config/_category_.yml @@ -2,4 +2,4 @@ label: 'âš™ï¸ Web3 config' collapsible: true collapsed: true link: null -position: 16 \ No newline at end of file +position: 7 diff --git a/docs/docs/guides/web3_plugin_guide/_category_.yml b/docs/docs/guides/web3_plugin_guide/_category_.yml index 42237f7ea38..8ab333571fd 100644 --- a/docs/docs/guides/web3_plugin_guide/_category_.yml +++ b/docs/docs/guides/web3_plugin_guide/_category_.yml @@ -2,4 +2,4 @@ label: 'ðŸ› ï¸ Web3 Plugin 🧩' collapsible: true collapsed: true link: null -position: 2 \ No newline at end of file +position: 12 diff --git a/docs/docs/guides/web3_providers_guide/_category_.yml b/docs/docs/guides/web3_providers_guide/_category_.yml index f426dbedf9a..2af69af2ea3 100644 --- a/docs/docs/guides/web3_providers_guide/_category_.yml +++ b/docs/docs/guides/web3_providers_guide/_category_.yml @@ -2,4 +2,4 @@ label: '🔌 Providers' collapsible: true collapsed: true link: null -position: 4 \ No newline at end of file +position: 2 diff --git a/docs/docs/guides/web3_upgrade_guide/_category_.yml b/docs/docs/guides/web3_upgrade_guide/_category_.yml index aeab3125b26..8335efbea79 100644 --- a/docs/docs/guides/web3_upgrade_guide/_category_.yml +++ b/docs/docs/guides/web3_upgrade_guide/_category_.yml @@ -2,4 +2,4 @@ label: 'â¬†ï¸ Upgrading' collapsible: true collapsed: true link: null -position: 11 \ No newline at end of file +position: 13 From 9086b98f25ef7ab9de0e699c00f462dca3e66f37 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Thu, 30 May 2024 06:22:53 -0700 Subject: [PATCH 10/25] fix(docs): mastering providers (#7070) * Improvements to Mastering Providers section * Consistent naming of injected providers --- .../docs/guides/getting_started/quickstart.md | 4 +- .../docs/guides/web3_providers_guide/index.md | 365 +++++++----------- 2 files changed, 131 insertions(+), 238 deletions(-) diff --git a/docs/docs/guides/getting_started/quickstart.md b/docs/docs/guides/getting_started/quickstart.md index c1db2a9fdc8..886b2690e19 100644 --- a/docs/docs/guides/getting_started/quickstart.md +++ b/docs/docs/guides/getting_started/quickstart.md @@ -43,7 +43,7 @@ import { Web3 } from 'web3'; ## Initialize `Web3` with a provider -[Providers](/guides/web3_providers_guide/) are objects that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. +[Providers](/guides/web3_providers_guide/) are services that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193), the Ethereum Provider JavaScript API, so any EIP-1193 provider can be used to initialize the `Web3` object. @@ -248,7 +248,7 @@ console.log(eventTransfer); Web3.js allows user to subscribe to events for real-time notification of important contract interactions. Here is an example of creating a subscription to the Uniswap token's `Transfer` event: :::note -You MUST initialize the `Web3` object with a [WebSocket](/guides/web3_providers_guide/#websocket-provider) provider to subscribe to live events. +HTTP providers do not support real-time event subscriptions. Use one of the other [provider types](/guides/web3_providers_guide/#providers-types) to subscribe to real-time events. ::: ```ts diff --git a/docs/docs/guides/web3_providers_guide/index.md b/docs/docs/guides/web3_providers_guide/index.md index e3ecc880cb0..1c1a0c334cb 100644 --- a/docs/docs/guides/web3_providers_guide/index.md +++ b/docs/docs/guides/web3_providers_guide/index.md @@ -5,20 +5,9 @@ sidebar_label: 'Mastering Providers' # Web3js providers overview +Providers are services that are responsible for enabling Web3.js connectivity with the Ethereum network. Using a provider to connect your application to an Ethereum node is necessary for querying data, sending transactions, and interacting with smart contracts. This guide will explore the different types of Web3.js providers, how to set them up, and how to use them in an application. -## Live code editor - - - -## Introduction - -web3.js providers are objects responsible for enabling connectivity with the Ethereum network in various ways. Connecting your web application to an Ethereum node is necessary for sending transactions, querying data, and interacting with smart contracts on the network. In this guide, we will explore the different types of providers available in web3.js, how to set them up, and how to use them in your code. - -Connecting to a chain happens through a provider. You can pass the provider to the constructor as in the following example: - -:::tip -If you want to subscribe to live events in the blockchain, you should use [`WebSocket provider`](#websocket-provider) or [`IPC provider`](#ipc-provider) -::: +A provider is typically supplied when constructing a new `Web3` object: ```typescript title='Initialize a provider' import { Web3 } from 'web3'; @@ -29,36 +18,38 @@ const web3 = new Web3(/* PROVIDER*/); await web3.eth.getBlockNumber(); ``` -The created `Web3` instance will use the passed provider to interact with the blockchain network. This interaction happens when sending a request and receiving the response, and possibly when listening to provider events (if the provider support this). +The new `Web3` instance will use the supplied provider to interact with the blockchain network. This interaction happens when sending requests and receiving responses, and possibly when listening to provider events (if the provider supports this). ## Providers Types -web3.js supports several types of providers, each with its own unique features or specific use cases. Here are the main types: +Web3.js supports several types of providers for different use cases. Here are the available types: -1. [HTTP Provider](/api/web3-providers-http/class/HttpProvider) -2. [WebSocket Provider](/api/web3-providers-ws/class/WebSocketProvider) -3. [IPC Provider (for Node.js)](/api/web3-providers-ipc/class/IpcProvider) -4. [Third-party Providers (Compliant with EIP 1193)](https://eips.ethereum.org/EIPS/eip-1193) +1. [HTTP Provider](#http-provider) +2. [WebSocket Provider](#websocket-provider) +3. [IPC Provider (for Node.js)](#ipc-provider) +4. [Injected Providers (Compliant with EIP 1193)](#injected-provider) -A string containing string url for `http`/`https` or `ws`/`wss` protocol. And when a string is passed, an instance of the compatible class above will be created accordingly. ex. WebSocketProvider instance will be created for string containing `ws` or `wss`. And you access this instance by calling `web3.provider` to read the provider and possibly register an event listener. +HTTP and WebSocket providers can be supplied as URL strings. All provider types can be supplied by constructing one of the [`SupportedProviders`](/api/web3/namespace/types#SupportedProviders) types. -:::tip -The passed provider can be either type `string` or one of the [`SupportedProviders`](/api/web3-core#SupportedProviders). And if it is passed as a string, then internally the compatible provider object will be created and used. -::: +Keep reading to learn more about the different types of providers and how to use them. ### HTTP Provider -``` ts title='Initialize HTTP Provider' +HTTP is a request-response protocol and does not support persistent connection, which means that HTTP providers are not suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). + +``` ts title='Initialize an HTTP Provider' import { Web3, HttpProvider } from 'web3'; +//supply an HTTP provider as a URL string //highlight-next-line const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); await web3.eth.getBlockNumber() // ↳ 18849658n -// or +// OR +//supply an HTTP provider by constructing a new HttpProvider //highlight-next-line const web3_2 = new Web3(new HttpProvider('https://mainnet.infura.io/v3/YOUR_INFURA_ID')); @@ -66,18 +57,53 @@ await web3.eth.getBlockNumber() // ↳ 18849658n ``` +#### Configuring HTTP Providers + +HTTP providers can be configured by including an [`HttpProviderOptions`](/api/web3-providers-http/interface/HttpProviderOptions/) object in the [`HttpProvider` constructor](/api/web3-providers-http/class/HttpProvider#constructor). The `HttpProviderOptions` type has a single property, `providerOptions`, which is a standard TypeScript [`RequestInit`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html) object. + +```ts title='Configuring an HTTP Provider' +import { Web3, HttpProvider } from 'web3'; + +const httpOptions = { + providerOptions: { + body: undefined, + cache: 'force-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + integrity: undefined, + keepalive: true, + method: 'GET', + mode: 'same-origin', + redirect: 'error', + referrer: undefined, + referrerPolicy: 'same-origin', + signal: undefined, + window: undefined, + } as RequestInit, +}; + +const web3 = new Web3(new HttpProvider('https://eth.llamarpc.com', httpOptions)); +``` + ### WebSocket provider +WebSockets support a persistent connection between a client and a server, which means they are suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). + ``` ts title='Initialize WS Provider' import { Web3, WebSocketProvider } from 'web3'; +//supply a WebSocket provider as a URL string //highlight-next-line const web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID'); await web3.eth.getBlockNumber(); // ↳ 18849658n -// or +// OR + +//supply a WebSocket provider by constructing a new WebSocketProvider //highlight-next-line const web3_2 = new Web3(new WebSocketProvider('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID')); @@ -85,8 +111,43 @@ await web3.eth.getBlockNumber(); // ↳ 18849658n ``` +#### Configuring WebSocket Providers + +The [`WebSocketProvider` constructor](/api/web3-providers-ws/class/WebSocketProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `WebSocketProvider`: the first parameter must be of type [`ClientRequestArgs`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) or of [`ClientOptions`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e5ee5eae6a592198e469ad9f412bab8d223fcbb6/types/ws/index.d.ts#L243) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). + +```ts title='Configuring a WebSocket Provider' +//include both optional parameters +const provider = new WebSocketProvider( + `ws://localhost:8545`, + { + headers: { + //for node services that require an API key in a header + 'x-api-key': '', + }, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); + +//OR include only ReconnectOptions +const provider = new WebSocketProvider( + `ws://localhost:8545`, + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); +``` + ### IPC Provider +IPC (inter-process communication) providers offer high-performance local communication and provide a faster alternative to HTTP providers. IPC providers are tailored for efficiency and excel in local environments, and also support real-time [event subscriptions](/guides/events_subscriptions/). + ``` ts title='Initialize IPC Provider' import { Web3 } from 'web3'; //highlight-next-line @@ -99,27 +160,49 @@ await web3.eth.getBlockNumber(); // ↳ 18849658n ``` -## Providers Priorities +#### Configuring IPC Providers + +The [`IpcProvider` constructor](/api/web3-providers-ipc/class/IpcProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `IpcProvider`: the first parameter must be of type [`SocketConstructorOpts`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). -There are multiple ways to set the provider. -```ts title='Setting a provider' -web3.setProvider(myProvider); -web3.eth.setProvider(myProvider); -web3.Contract.setProvider(myProvider); -contractInstance.setProvider(myProvider); + +```ts title='Configuring an IPC Provider' +//include both optional parameters +const provider = new IpcProvider( + '/Users/myuser/Library/Ethereum/geth.ipc', + { + writable: false, + }, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); + +//OR include only ReconnectOptions +const provider = new IpcProvider( + '/Users/myuser/Library/Ethereum/geth.ipc', + {}, + { + delay: 500, + autoReconnect: true, + maxAttempts: 10, + } +); ``` -The key rule for setting provider is as follows: +### Injected Provider -1. Any provider set on the higher level will be applied to all lower levels. e.g. Any provider set using `web3.setProvider` will also be applied to `web3.eth` object. -2. For contracts `web3.Contract.setProvider` can be used to set provider for **all instances** of contracts created by `web3.eth.Contract`. +Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet/). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193). Injected providers support real-time [event subscriptions](/guides/events_subscriptions/). Continue reading for an [example](#injected-provider-1) of using an injected provider. ---- +## Provider Origins + +A provider may be local to an application (i.e. running on the same machine) or remote (i.e. running on a third-party server). Injected providers are a third alternative that are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. Keep reading for more examples that illustrate how to work with local, remote, and injected providers. -## Usage Scenarios +### Local Provider -### Local Geth Node +Local providers can usually be accessed via IPC, HTTP, or WebSocket. The following examples demonstrates using a local Geth node to supply the Web3.js provider. ```typescript title='IPC, HTTP and WS provider' import { Web3 } from 'web3'; @@ -144,7 +227,9 @@ web3.setProvider('ws://localhost:8546'); web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546')); ``` -### Remote Node Provider +### Remote Provider + +Services like [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/), and [QuickNode](https://www.quicknode.com/) offer Ethereum node services that can be accessed via HTTP or Websocket. ```ts title='Alchemy, Infura, etc' // like Alchemy (https://www.alchemyapi.io/supernode) @@ -155,9 +240,11 @@ const web3 = new Web3('https://eth-mainnet.alchemyapi.io/v2/your-api-key'); ### Injected Provider -As stated above, the injected provider should be in compliance with [EIP-1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md). And it is tested with Ganache provider, Hardhat provider, and Incubed (IN3) as a provider. +Injected providers are supplied by an external third-party, most often a wallet or a web browser that is designed to be used with the Ethereum network. In addition to providing network connectivity, injected providers often supply one or more [accounts](/guides/wallet/). Web3.js supports any injected provider that is compliant with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) and has been tested with multiple EIP-1193 providers, including [MetaMask](https://docs.metamask.io/wallet/reference/provider-api/), [Hardhat](https://hardhat.org/hardhat-runner/docs/advanced/hardhat-runtime-environment), and [Incubed (IN3)](https://in3.readthedocs.io/en/develop/index.html). -The web3.js 4.x Provider specifications are defined in [web3 base provider](https://github.com/ChainSafe/web3.js/blob/4.x/packages/web3-types/src/web3_base_provider.ts) for Injected Providers. +:::note +The following example should be run in a browser with the MetaMask extension installed. +::: ```html title='E.g, Metamask' @@ -186,197 +273,3 @@ The web3.js 4.x Provider specifications are defined in [web3 base provider](http }); ``` - -Note that the above code should be hosted in a web server (that could be a simple local web server), because many browser does not support this feature for static files located on your machine. - -## Provider Options - -There are differences in the objects that could be passed in the Provider constructors. - -### HttpProvider - -The options is of type `HttpProviderOptions`, which is an object with a single key named `providerOptions` and its value is an object of type `RequestInit`. -Regarding `RequestInit` see [microsoft's github](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_dom_d_.requestinit.html). - -```ts title='HTTP Provider example' -const httpOptions = { - providerOptions: { - body: undefined, - cache: 'force-cache', - credentials: 'same-origin', - headers: { - 'Content-Type': 'application/json', - }, - integrity: 'foo', - keepalive: true, - method: 'GET', - mode: 'same-origin', - redirect: 'error', - referrer: 'foo', - referrerPolicy: 'same-origin', - signal: undefined, - window: undefined, - } as RequestInit, -}; -``` - -### WebSocketProvider - -Use WebSocketProvider to connect to a Node using a WebSocket connection, i.e. over the `ws` or `wss` protocol. - -The options object is of type `ClientRequestArgs` or of `ClientOptions`. See [here](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) for `ClientRequestArgs` and [here](https://github.com/websockets/ws) for `ClientOptions`. - -The second option parameter can be given regarding reconnecting. And here is its type: - -```ts title='WebSocket Provider example' -// this is the same options interface used for both WebSocketProvider and IpcProvider -type ReconnectOptions = { - autoReconnect: boolean, // default: `true` - delay: number, // default: `5000` - maxAttempts: number, // default: `5` -}; - -``` - -```ts title='Instantiation of WebSocket Provider' -const provider = new WebSocketProvider( - `ws://localhost:8545`, - { - headers: { - // to provide the API key if the Node requires the key to be inside the `headers` for example: - 'x-api-key': '', - }, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -The second and the third parameters are both optional. And, for example, the second parameter could be an empty object or undefined, like in the following example: - -```ts title='Instantiation of WebSocket Provider' -const provider = new WebSocketProvider( - `ws://localhost:8545`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -Below is an example for the passed options: - -```ts title='WS Provider options example' -let clientOptions: ClientOptions = { - // Useful for credentialed urls, e.g: ws://username:password@localhost:8546 - headers: { - authorization: 'Basic username:password', - }, - maxPayload: 100000000, -}; - -const reconnectOptions: ReconnectOptions = { - autoReconnect: true, - delay: 5000, - maxAttempts: 5, -}; -``` - -### IpcProvider - -The IPC Provider could be used in node.js dapps when running a local node. And it provide the most secure connection. - -It accepts a second parameter called `socketOptions`. And, its type is `SocketConstructorOpts`. See [here](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html) for full details. And here is its interface: - -```ts title='IPC Provider options' -// for more check https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_net_d_._net_.socketconstructoropts.html -interface SocketConstructorOpts { - fd?: number | undefined; - allowHalfOpen?: boolean | undefined; - readable?: boolean | undefined; - writable?: boolean | undefined; -} -``` - -And, the third parameter is called `reconnectOptions` that is of the type `ReconnectOptions`. It can be given to control: auto-reconnecting, delay and max tries attempts. And here its type: - -```ts -// this is the same options interface used for both WebSocketProvider and IpcProvider -type ReconnectOptions = { - autoReconnect: boolean, // default: `true` - delay: number, // default: `5000` - maxAttempts: number, // default: `5` -}; -``` - -Below is an example for the passed options for each version: - -```ts title='Options Example' -let clientOptions: SocketConstructorOpts = { - allowHalfOpen: false; - readable: true; - writable: true; -}; - -const reconnectOptions: ReconnectOptions = { - autoReconnect: true, - delay: 5000, - maxAttempts: 5, -}; -``` - -And here is a sample instantiation for the `IpcProvider`: - -```ts title='IPC Provider example' -const provider = new IpcProvider( - `path.ipc`, - { - writable: false, - }, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -The second and the third parameters are both optional. And, for example, the second parameter could be an empty object or undefined. - -```ts title='IPC Provider example' -const provider = new IpcProvider( - `path.ipc`, - {}, - { - delay: 500, - autoReconnect: true, - maxAttempts: 10, - } -); -``` - -:::info -This section applies for both `IpcProvider` and `WebSocketProvider`. -::: - -The error message, for the max reconnect attempts, will contain the value of the variable `maxAttempts` as follows: - -`` `Maximum number of reconnect attempts reached! (${maxAttempts})` `` - -And here is how to catch the error, if max attempts reached when there is auto reconnecting: - -```ts title='Error message for reconnect attempts' -provider.on('error', (error) => { - if (error.message.startsWith('Maximum number of reconnect attempts reached!')) { - // the `error.message` will be `Maximum number of reconnect attempts reached! (${maxAttempts})` - // the `maxAttempts` is equal to the provided value by the user, or the default value `5`. - } -}); -``` - - From 51d216fbe63e35d3792e9508705fa4b0b1612378 Mon Sep 17 00:00:00 2001 From: Oleksii Kosynskyi Date: Sun, 2 Jun 2024 21:54:10 -0400 Subject: [PATCH 11/25] Remove .snyk files (#7073) * add .snyk file * fix snyk scan for all projects * Delete .snyk * Remove snyk files * remove .snyk files --- docs/.snyk | 36 ------------------------- packages/web3/.snyk | 21 --------------- tools/eslint-config-base-web3/.snyk | 41 ----------------------------- 3 files changed, 98 deletions(-) delete mode 100644 docs/.snyk delete mode 100644 packages/web3/.snyk delete mode 100644 tools/eslint-config-base-web3/.snyk diff --git a/docs/.snyk b/docs/.snyk deleted file mode 100644 index b29b615196e..00000000000 --- a/docs/.snyk +++ /dev/null @@ -1,36 +0,0 @@ -# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. -version: v1.25.0 -# ignores vulnerabilities until expiry date; change duration by modifying expiry date -ignore: - SNYK-JS-BRACES-6838727: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:07.153Z - created: 2024-05-27T17:29:07.159Z - SNYK-JS-EXPRESS-6474509: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:31.142Z - created: 2024-05-27T17:29:31.149Z - SNYK-JS-INFLIGHT-6095116: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:51.622Z - created: 2024-05-27T17:29:51.628Z - SNYK-JS-MICROMATCH-6838728: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:30:47.237Z - created: 2024-05-27T17:30:47.240Z - SNYK-JS-SERIALIZEJAVASCRIPT-6147607: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:31:06.652Z - created: 2024-05-27T17:31:06.656Z - SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T20:52:00.793Z - created: 2024-05-27T20:52:00.797Z - -patch: {} diff --git a/packages/web3/.snyk b/packages/web3/.snyk deleted file mode 100644 index 5b289bc1640..00000000000 --- a/packages/web3/.snyk +++ /dev/null @@ -1,21 +0,0 @@ -# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. -version: v1.25.0 -# ignores vulnerabilities until expiry date; change duration by modifying expiry date -ignore: - SNYK-JS-WEB3-174533: - - '*': - reason: Ignore test issue - expires: 3024-06-26T17:16:53.075Z - created: 2024-05-27T17:16:53.080Z - SNYK-JS-JSON5-3182856: - - '*': - reason: Eslint problem - expires: 3024-06-26T20:53:53.640Z - created: 2024-05-27T20:53:53.644Z - SNYK-JS-SEMVER-3247795: - - '*': - reason: Eslint problem - expires: 3024-06-26T20:54:20.755Z - created: 2024-05-27T20:54:20.759Z - -patch: {} diff --git a/tools/eslint-config-base-web3/.snyk b/tools/eslint-config-base-web3/.snyk deleted file mode 100644 index f0ce4e19c9c..00000000000 --- a/tools/eslint-config-base-web3/.snyk +++ /dev/null @@ -1,41 +0,0 @@ -# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. -version: v1.25.0 -# ignores vulnerabilities until expiry date; change duration by modifying expiry date -ignore: - SNYK-JS-BRACES-6838727: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:07.153Z - created: 2024-05-27T17:29:07.159Z - SNYK-JS-EXPRESS-6474509: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:31.142Z - created: 2024-05-27T17:29:31.149Z - SNYK-JS-INFLIGHT-6095116: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T17:29:51.622Z - created: 2024-05-27T17:29:51.628Z - SNYK-JS-MICROMATCH-6838728: - - '*': - reason: Eslint issue - expires: 3024-06-26T17:30:47.237Z - created: 2024-05-27T17:30:47.240Z - SNYK-JS-WEBPACKDEVMIDDLEWARE-6476555: - - '*': - reason: Docusaurus issue - expires: 3024-06-26T20:52:00.793Z - created: 2024-05-27T20:52:00.797Z - SNYK-JS-JSON5-3182856: - - '*': - reason: Eslint problem - expires: 3024-06-26T20:53:53.640Z - created: 2024-05-27T20:53:53.644Z - SNYK-JS-SEMVER-3247795: - - '*': - reason: Eslint problem - expires: 3024-06-26T20:54:20.755Z - created: 2024-05-27T20:54:20.759Z - -patch: {} From 8f627495717df387f4170793d438b134a8e0a08a Mon Sep 17 00:00:00 2001 From: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:07:20 +0200 Subject: [PATCH 12/25] 100% Coverage web3-utills (#7042) * increase unit tests for SocketProvider * add a test for SocketProvider * add a test for PromiseHelper * add unit tests for utils * remove un visited code branch * fix linting issue * point to a pice of code to investigate * fix linting issue * add coverage to hash * cover json-rpc tests * cover socket provider file * add coverage string manipulation * add coverage to formatters.ts * fix failing tests * update hash * run prettier * remove unintended cases for formatter and convert --------- Co-authored-by: Alex Luu --- .gitignore | 2 + packages/web3-utils/src/converters.ts | 37 +- packages/web3-utils/src/formatter.ts | 12 +- packages/web3-utils/src/hash.ts | 17 +- packages/web3-utils/src/json_rpc.ts | 2 +- packages/web3-utils/src/promise_helpers.ts | 39 +- packages/web3-utils/src/socket_provider.ts | 30 +- .../web3-utils/test/fixtures/converters.ts | 72 ++- .../web3-utils/test/fixtures/formatter.ts | 1 + packages/web3-utils/test/fixtures/hash.ts | 14 +- packages/web3-utils/test/fixtures/json_rpc.ts | 40 ++ .../test/fixtures/string_manipulation.ts | 6 +- .../test/unit/chunk_response_parser.test.ts | 14 + .../web3-utils/test/unit/converters.test.ts | 69 ++- .../web3-utils/test/unit/formatter.test.ts | 23 +- packages/web3-utils/test/unit/hash.test.ts | 8 + packages/web3-utils/test/unit/index.test.ts | 64 +++ .../web3-utils/test/unit/json_rpc.test.ts | 63 ++- packages/web3-utils/test/unit/objects.test.ts | 9 + .../test/unit/promise_helpers.test.ts | 8 + .../test/unit/socket_provider.test.ts | 529 +++++++++++++++++- .../test/unit/web3_deferred_promise.test.ts | 13 + 22 files changed, 959 insertions(+), 113 deletions(-) create mode 100644 packages/web3-utils/test/unit/index.test.ts diff --git a/.gitignore b/.gitignore index c22337c0c9a..72f88324900 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,5 @@ packages/web3/.in3/ benchmark-data.txt .eslintcache + +.history \ No newline at end of file diff --git a/packages/web3-utils/src/converters.ts b/packages/web3-utils/src/converters.ts index 6649bef1481..9c94a4332b0 100644 --- a/packages/web3-utils/src/converters.ts +++ b/packages/web3-utils/src/converters.ts @@ -79,7 +79,8 @@ export const ethUnitMap = { tether: BigInt('1000000000000000000000000000000'), }; -const PrecisionLossWarning = 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods'; +const PrecisionLossWarning = + 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods'; export type EtherUnits = keyof typeof ethUnitMap; /** @@ -366,7 +367,7 @@ export const toHex = ( return returnType ? 'bigint' : numberToHex(value); } - if(isUint8Array(value)) { + if (isUint8Array(value)) { return returnType ? 'bytes' : bytesToHex(value); } @@ -386,6 +387,15 @@ export const toHex = ( return returnType ? 'bytes' : `0x${value}`; } if (isHex(value) && !isInt(value) && isUInt(value)) { + // This condition seems problematic because meeting + // both conditions `!isInt(value) && isUInt(value)` should be impossible. + // But a value pass for those conditions: "101611154195520776335741463917853444671577865378275924493376429267637792638729" + // Note that according to the docs: it is supposed to be treated as a string (https://docs.web3js.org/guides/web3_upgrade_guide/x/web3_utils_migration_guide#conversion-to-hex) + // In short, the strange is that isInt(value) is false but isUInt(value) is true for the value above. + // TODO: isUInt(value) should be investigated. + + // However, if `toHex('101611154195520776335741463917853444671577865378275924493376429267637792638729', true)` is called, it will return `true`. + // But, if `toHex('101611154195520776335741463917853444671577865378275924493376429267637792638729')` is called, it will throw inside `numberToHex`. return returnType ? 'uint' : numberToHex(value); } @@ -419,14 +429,14 @@ export const toHex = ( */ export const toNumber = (value: Numbers): number | bigint => { if (typeof value === 'number') { - if (value > 1e+20) { - console.warn(PrecisionLossWarning) - // JavaScript converts numbers >= 10^21 to scientific notation when coerced to strings, - // leading to potential parsing errors and incorrect representations. - // For instance, String(10000000000000000000000) yields '1e+22'. - // Using BigInt prevents this - return BigInt(value); - } + if (value > 1e20) { + console.warn(PrecisionLossWarning); + // JavaScript converts numbers >= 10^21 to scientific notation when coerced to strings, + // leading to potential parsing errors and incorrect representations. + // For instance, String(10000000000000000000000) yields '1e+22'. + // Using BigInt prevents this + return BigInt(value); + } return value; } @@ -506,10 +516,9 @@ export const fromWei = (number: Numbers, unit: EtherUnits | number): string => { if (unit < 0 || !Number.isInteger(unit)) { throw new InvalidIntegerError(unit); } - denomination = bigintPower(BigInt(10),BigInt(unit)); + denomination = bigintPower(BigInt(10), BigInt(unit)); } - // value in wei would always be integer // 13456789, 1234 const value = String(toNumber(number)); @@ -575,8 +584,8 @@ export const toWei = (number: Numbers, unit: EtherUnits | number): string => { if (unit < 0 || !Number.isInteger(unit)) { throw new InvalidIntegerError(unit); } - - denomination = bigintPower(BigInt(10),BigInt(unit)); + + denomination = bigintPower(BigInt(10), BigInt(unit)); } let parsedNumber = number; diff --git a/packages/web3-utils/src/formatter.ts b/packages/web3-utils/src/formatter.ts index 42062add5c6..665965a8eed 100644 --- a/packages/web3-utils/src/formatter.ts +++ b/packages/web3-utils/src/formatter.ts @@ -57,10 +57,8 @@ const findSchemaByDataPath = ( for (const dataPart of dataPath) { if (result.oneOf && previousDataPath) { - const path = oneOfPath.find(function (element: [string, number]) { - return (this as unknown as string) === element[0]; - }, previousDataPath ?? ''); - + const currentDataPath = previousDataPath; + const path = oneOfPath.find(([key]) => key === currentDataPath); if (path && path[0] === previousDataPath) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access result = result.oneOf[path[1]]; @@ -75,10 +73,6 @@ const findSchemaByDataPath = ( } else if (result.items && (result.items as JsonSchema).properties) { const node = (result.items as JsonSchema).properties as Record; - if (!node) { - return undefined; - } - result = node[dataPart]; } else if (result.items && isObject(result.items)) { result = result.items; @@ -307,7 +301,7 @@ export const convert = ( // If value is an object, recurse into it if (isObject(value)) { - convert(value, schema, dataPath, format); + convert(value, schema, dataPath, format, oneOfPath); dataPath.pop(); continue; } diff --git a/packages/web3-utils/src/hash.ts b/packages/web3-utils/src/hash.ts index 6e498138c29..0289a429a52 100644 --- a/packages/web3-utils/src/hash.ts +++ b/packages/web3-utils/src/hash.ts @@ -17,25 +17,25 @@ along with web3.js. If not, see . /** * This package provides utility functions for Ethereum dapps and other web3.js packages. - * + * * For using Utils functions, first install Web3 package using `npm i web3` or `yarn add web3`. - * After that, Web3 Utils functions will be available as mentioned below. + * After that, Web3 Utils functions will be available as mentioned below. * ```ts * import { Web3 } from 'web3'; * const web3 = new Web3(); - * + * * const value = web3.utils.fromWei("1", "ether") - * + * * ``` - * + * * For using individual package install `web3-utils` package using `npm i web3-utils` or `yarn add web3-utils` and only import required functions. - * This is more efficient approach for building lightweight applications. + * This is more efficient approach for building lightweight applications. * ```ts * import { fromWei, soliditySha3Raw } from 'web3-utils'; - * + * * console.log(fromWei("1", "ether")); * console.log(soliditySha3Raw({ type: "string", value: "helloworld" })) - * + * * ``` * @module Utils */ @@ -172,7 +172,6 @@ const getType = (arg: Sha3Input): [string, EncodingTypes] => { if (Array.isArray(arg)) { throw new Error('Autodetection of array types is not supported.'); } - let type; let value; // if type is given diff --git a/packages/web3-utils/src/json_rpc.ts b/packages/web3-utils/src/json_rpc.ts index 573d39197e3..495a425611f 100644 --- a/packages/web3-utils/src/json_rpc.ts +++ b/packages/web3-utils/src/json_rpc.ts @@ -99,7 +99,7 @@ let requestIdSeed: number | undefined; /** * Optionally use to make the jsonrpc `id` start from a specific number. * Without calling this function, the `id` will be filled with a Uuid. - * But after this being called with a number, the `id` will be a number staring from the provided `start` variable. + * But after this being called with a number, the `id` will be a number starting from the provided `start` variable. * However, if `undefined` was passed to this function, the `id` will be a Uuid again. * @param start - a number to start incrementing from. * Or `undefined` to use a new Uuid (this is the default behavior) diff --git a/packages/web3-utils/src/promise_helpers.ts b/packages/web3-utils/src/promise_helpers.ts index c8e211fbbb7..a2140a2d1c5 100644 --- a/packages/web3-utils/src/promise_helpers.ts +++ b/packages/web3-utils/src/promise_helpers.ts @@ -20,7 +20,6 @@ import { isNullish } from 'web3-validator'; export type Timer = ReturnType; export type Timeout = ReturnType; - /** * An alternative to the node function `isPromise` that exists in `util/types` because it is not available on the browser. * @param object - to check if it is a `Promise` @@ -74,7 +73,6 @@ export async function waitWithTimeout( return result; } - /** * Repeatedly calls an async function with a given interval until the result of the function is defined (not undefined or null), * or until a timeout is reached. It returns promise and intervalId. @@ -85,25 +83,27 @@ export function pollTillDefinedAndReturnIntervalId( func: AsyncFunction, interval: number, ): [Promise>, Timer] { - let intervalId: Timer | undefined; const polledRes = new Promise>((resolve, reject) => { - intervalId = setInterval(function intervalCallbackFunc(){ - (async () => { - try { - const res = await waitWithTimeout(func, interval); - - if (!isNullish(res)) { + intervalId = setInterval( + (function intervalCallbackFunc() { + (async () => { + try { + const res = await waitWithTimeout(func, interval); + + if (!isNullish(res)) { + clearInterval(intervalId); + resolve(res as unknown as Exclude); + } + } catch (error) { clearInterval(intervalId); - resolve(res as unknown as Exclude); + reject(error); } - } catch (error) { - clearInterval(intervalId); - reject(error); - } - })() as unknown; - return intervalCallbackFunc;}() // this will immediate invoke first call - , interval); + })() as unknown; + return intervalCallbackFunc; + })(), // this will immediate invoke first call + interval, + ); }); return [polledRes as unknown as Promise>, intervalId!]; @@ -113,7 +113,7 @@ export function pollTillDefinedAndReturnIntervalId( * Repeatedly calls an async function with a given interval until the result of the function is defined (not undefined or null), * or until a timeout is reached. * pollTillDefinedAndReturnIntervalId() function should be used instead of pollTillDefined if you need IntervalId in result. - * This function will be deprecated in next major release so use pollTillDefinedAndReturnIntervalId(). + * This function will be deprecated in next major release so use pollTillDefinedAndReturnIntervalId(). * @param func - The function to call. * @param interval - The interval in milliseconds. */ @@ -146,7 +146,7 @@ export function rejectIfTimeout(timeout: number, error: Error): [Timer, Promise< /** * Sets an interval that repeatedly executes the given cond function with the specified interval between each call. * If the condition is met, the interval is cleared and a Promise that rejects with the returned value is returned. - * @param cond - The function/confition to call. + * @param cond - The function/condition to call. * @param interval - The interval in milliseconds. * @returns - an array with the interval ID and the Promise. */ @@ -168,4 +168,3 @@ export function rejectIfConditionAtInterval( }); return [intervalId!, rejectIfCondition]; } - diff --git a/packages/web3-utils/src/socket_provider.ts b/packages/web3-utils/src/socket_provider.ts index d847dcbccc9..0a73fb8378f 100644 --- a/packages/web3-utils/src/socket_provider.ts +++ b/packages/web3-utils/src/socket_provider.ts @@ -187,13 +187,13 @@ export abstract class SocketProvider< protected _validateProviderPath(path: string): boolean { return !!path; } - + /** * * @returns the pendingRequestQueue size */ // eslint-disable-next-line class-methods-use-this - public getPendingRequestQueueSize() { + public getPendingRequestQueueSize() { return this._pendingRequestsQueue.size; } @@ -350,32 +350,34 @@ export abstract class SocketProvider< /** * Safely disconnects the socket, async and waits for request size to be 0 before disconnecting - * @param forceDisconnect - If true, will clear queue after 5 attempts of waiting for both pending and sent queue to be 0 + * @param forceDisconnect - If true, will clear queue after 5 attempts of waiting for both pending and sent queue to be 0 * @param ms - Determines the ms of setInterval * @param code - The code to be sent to the server * @param data - The data to be sent to the server */ - public async safeDisconnect(code?: number, data?: string, forceDisconnect = false,ms = 1000) { + public async safeDisconnect(code?: number, data?: string, forceDisconnect = false, ms = 1000) { let retryAttempt = 0; - const checkQueue = async () => + const checkQueue = async () => new Promise(resolve => { const interval = setInterval(() => { - if (forceDisconnect && retryAttempt === 5) { + if (forceDisconnect && retryAttempt >= 5) { this.clearQueues(); } - if (this.getPendingRequestQueueSize() === 0 && this.getSentRequestsQueueSize() === 0) { + if ( + this.getPendingRequestQueueSize() === 0 && + this.getSentRequestsQueueSize() === 0 + ) { clearInterval(interval); resolve(true); } - retryAttempt+=1; - }, ms) - }) - + retryAttempt += 1; + }, ms); + }); + await checkQueue(); this.disconnect(code, data); } - /** * Removes all listeners for the specified event type. * @param type - The event type to remove the listeners for @@ -512,7 +514,7 @@ export abstract class SocketProvider< if (isNullish(responses) || responses.length === 0) { return; } - + for (const response of responses) { if ( jsonRpc.isResponseWithNotification(response as JsonRpcNotification) && @@ -544,7 +546,7 @@ export abstract class SocketProvider< this._sentRequestsQueue.delete(requestId); } } - + public clearQueues(event?: ConnectionEvent) { this._clearQueues(event); } diff --git a/packages/web3-utils/test/fixtures/converters.ts b/packages/web3-utils/test/fixtures/converters.ts index 9f0324b68ad..cecb0b3fafb 100644 --- a/packages/web3-utils/test/fixtures/converters.ts +++ b/packages/web3-utils/test/fixtures/converters.ts @@ -235,21 +235,20 @@ export const toHexValidData: [Numbers | Bytes | Address | boolean, [HexString, V ], ['-0x01', ['-0x1', 'int256']], ['123c', ['0x123c', 'bytes']], - [new Uint8Array([ - 221, 128, 128, 128, 148, 186, 248, - 242, 159, 130, 231, 84, 254, 199, - 252, 69, 21, 58, 104, 102, 201, - 137, 255, 3, 196, 10, 128, 128, - 128, 128 - ]), ['0xdd80808094baf8f29f82e754fec7fc45153a6866c989ff03c40a80808080', 'bytes']], - [Buffer.from([ - 221, 128, 128, 128, 148, 186, 248, - 242, 159, 130, 231, 84, 254, 199, - 252, 69, 21, 58, 104, 102, 201, - 137, 255, 3, 196, 10, 128, 128, - 128, 128 - ]), ['0xdd80808094baf8f29f82e754fec7fc45153a6866c989ff03c40a80808080', 'bytes']] - + [ + new Uint8Array([ + 221, 128, 128, 128, 148, 186, 248, 242, 159, 130, 231, 84, 254, 199, 252, 69, 21, 58, + 104, 102, 201, 137, 255, 3, 196, 10, 128, 128, 128, 128, + ]), + ['0xdd80808094baf8f29f82e754fec7fc45153a6866c989ff03c40a80808080', 'bytes'], + ], + [ + Buffer.from([ + 221, 128, 128, 128, 148, 186, 248, 242, 159, 130, 231, 84, 254, 199, 252, 69, 21, 58, + 104, 102, 201, 137, 255, 3, 196, 10, 128, 128, 128, 128, + ]), + ['0xdd80808094baf8f29f82e754fec7fc45153a6866c989ff03c40a80808080', 'bytes'], + ], ]; export const toHexInvalidData: [any, string][] = [ @@ -320,15 +319,15 @@ const conversionBaseData: [[Numbers, EtherUnits | number], string][] = [ export const fromWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ ...conversionBaseData, - [['0xff', 'wei'], '255'], - [[1e+22, 'ether'], '10000'], - [[19999999999999991611392, 'ether'], '19999.999999999991611392'], - [[1.9999999999999991611392e+22, 'ether'], '19999.999999999991611392'], + [['0xff', 'wei'], '255'], + [[1e22, 'ether'], '10000'], + [[19999999999999991611392, 'ether'], '19999.999999999991611392'], + [[1.9999999999999991611392e22, 'ether'], '19999.999999999991611392'], [['1000000', 'ether'], '0.000000000001'], [['1123456789123456789', 'ether'], '1.123456789123456789'], [['1123', 'kwei'], '1.123'], - [['1234100' ,'kwei'], '1234.1'], - [['3308685546611893', 'ether'], '0.003308685546611893'] + [['1234100', 'kwei'], '1234.1'], + [['3308685546611893', 'ether'], '0.003308685546611893'], ]; export const toWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ @@ -339,17 +338,24 @@ export const toWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [ [['1000000', 'ether'], 0.000000000001], [['1123456789123456789', 'ether'], '1.123456789123456789123'], [['1123', 'kwei'], '1.12345'], - [['1234100' ,'kwei'], '1234.1'], + [['1234100', 'kwei'], '1234.1'], [['3308685546611893', 'ether'], '0.0033086855466118933'], [['1123', 'kwei'], 1.12345], - ]; export const toWeiValidDataWarnings: [[Numbers, EtherUnits], string][] = [ - [[0.0000000000000000000001, 'ether'], 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods'], - [[0.0000000000000000000001, 'ether'], 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods'], - [[1999999000000009900000, 'kwei'], 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods'], - + [ + [0.0000000000000000000001, 'ether'], + 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods', + ], + [ + [0.0000000000000000000001, 'ether'], + 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods', + ], + [ + [1999999000000009900000, 'kwei'], + 'Warning: Using type `number` with values that are large or contain many decimals may cause loss of precision, it is recommended to use type `string` or `BigInt` when using conversion methods', + ], ]; export const fromWeiInvalidData: [[any, any], string][] = [ @@ -362,8 +368,14 @@ export const fromWeiInvalidData: [[any, any], string][] = [ [[{}, 'kwei'], 'Invalid value given "{}". Error: can not parse as number data'], [['data', 'kwei'], 'Invalid value given "data". Error: can not parse as number data.'], [['1234', 'uwei'], 'Invalid value given "uwei". Error: invalid unit.'], - [['1234', -1], 'Invalid value given "-1". Error: not a valid unit. Must be a positive integer.'], - [['1234', 3.3], 'Invalid value given "3.3". Error: not a valid unit. Must be a positive integer.'] + [ + ['1234', -1], + 'Invalid value given "-1". Error: not a valid unit. Must be a positive integer.', + ], + [ + ['1234', 3.3], + 'Invalid value given "3.3". Error: not a valid unit. Must be a positive integer.', + ], ]; export const toWeiInvalidData: [[any, any], string][] = [ @@ -374,6 +386,7 @@ export const toWeiInvalidData: [[any, any], string][] = [ [[{}, 'kwei'], 'value "{}" at "/0" must pass "number" validation'], [['data', 'kwei'], 'value "data" at "/0" must pass "number" validation'], [['1234', 'uwei'], 'Invalid value given "uwei". Error: invalid unit.'], + [['123', -1], 'Invalid value given "-1". Error: not a valid unit. Must be a positive integer.'], ]; export const toCheckSumValidData: [string, string][] = [ ['0x0089d53f703f7e0843953d48133f74ce247184c2', '0x0089d53F703f7E0843953D48133f74cE247184c2'], @@ -397,6 +410,7 @@ export const bytesToUint8ArrayValidData: [Bytes, Uint8Array][] = [ ['0x1234', new Uint8Array([18, 52])], ['0x1234', new Uint8Array([18, 52])], [new Uint8Array(hexToBytes('0c12')), new Uint8Array(hexToBytes('0c12'))], + [[72, 12] as any, new Uint8Array([72, 12])], ]; export const toBigIntValidData: [any, bigint][] = [ diff --git a/packages/web3-utils/test/fixtures/formatter.ts b/packages/web3-utils/test/fixtures/formatter.ts index 7437373d708..5d44b05df2d 100644 --- a/packages/web3-utils/test/fixtures/formatter.ts +++ b/packages/web3-utils/test/fixtures/formatter.ts @@ -55,4 +55,5 @@ export const convertScalarValueValid: [[any, any, any], any][] = [ hexToBytes('0x00000000000000000000000000000000000000000000000000000000000000ff'), ), ], + [[255, 'bytes32', { bytes: 'invalidFormat' }], 255], // return original value when erroring ]; diff --git a/packages/web3-utils/test/fixtures/hash.ts b/packages/web3-utils/test/fixtures/hash.ts index 6bfe9f63f33..1869dd10fec 100644 --- a/packages/web3-utils/test/fixtures/hash.ts +++ b/packages/web3-utils/test/fixtures/hash.ts @@ -256,6 +256,7 @@ export const encodePackData: [TypedObject[] | TypedObjectAbbreviated[], any][] = '0x12480000000000000000000000000000000000000000000000000000000000003c69a194aaf415ba5d6afca734660d0a3d45acdc05d54cd1ca89a8988e7625b4', ], [[{ type: 'bytes4[]', value: ['0x11223344', '0x22334455'] }], '0x1122334422334455'], + [[{ type: '', value: '31323334' }], '0x'], ]; export const encodePackedInvalidData: [any, string][] = [ @@ -285,9 +286,13 @@ export const encodePackedInvalidData: [any, string][] = [ { type: 'bytes32', value: '0x1' }, 'Invalid value given "0x1". Error: can not parse as byte data.', ], + [ + [[{ type: 'string', value: '31323334' }], [{ type: '', value: '31323334' }]], + 'Autodetection of array types is not supported.', + ], ]; -export const keccak256ValidData: [string | Uint8Array | bigint, string][] = [ +export const keccak256ValidData: [string | Uint8Array | bigint | number[], string][] = [ ['my data', '0x8e0c48154711500d6fa119cc31df4dec339091e8b426cf4109a769fe89baad31'], [ new Uint8Array(Buffer.from('my data')), @@ -298,6 +303,8 @@ export const keccak256ValidData: [string | Uint8Array | bigint, string][] = [ '0x2d19cd91fbcc44e6412f92c11da7907cdedb1ace04c47447b42a61f1cd63b85a', ], [BigInt(3), '0x2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de'], + [[0x3], '0x69c322e3248a5dfc29d73c5b0553b0185a35cd5bb6386747517ef7e53b15e287'], + [new Uint8Array([0x3]), '0x69c322e3248a5dfc29d73c5b0553b0185a35cd5bb6386747517ef7e53b15e287'], ]; export const elementaryNameValidData: [any, string][] = [ @@ -349,3 +356,8 @@ export const soliditySha3BigIntValidData: [Sha3Input[], string][] = [ return keccak256(abi.encodePacked(int(90071992547409))) ;} */ ]; + +export const getStorageSlotNumForLongStringValidData: [string | number, string | undefined][] = [ + [0, '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563'], + ['0', '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563'], +]; diff --git a/packages/web3-utils/test/fixtures/json_rpc.ts b/packages/web3-utils/test/fixtures/json_rpc.ts index 516711abceb..d801fa91587 100644 --- a/packages/web3-utils/test/fixtures/json_rpc.ts +++ b/packages/web3-utils/test/fixtures/json_rpc.ts @@ -18,6 +18,7 @@ import { JsonRpcNotification, SubscriptionParams } from 'web3-types'; const responseWithResult = { jsonrpc: '2.0', id: 1, result: '' }; const responseWithError = { jsonrpc: '2.0', id: 1, error: { code: 1, message: 'string' } }; +const responseWithRpcError = { jsonrpc: '2.0', id: 1, error: { code: -32000, message: 'string' } }; const responseWithSubscription = { id: 1, jsonrpc: '2.0', result: '' }; const responseWithNotfication = { jsonrpc: '2.0', @@ -27,11 +28,13 @@ const responseWithNotfication = { export const isResponseWithResultValidTest: [any, boolean][] = [ [responseWithResult, true], [responseWithError, false], + [{ ...responseWithResult, id: '1' }, true], ]; export const isResponseWithErrorValidTest: [any, boolean][] = [ [responseWithResult, false], [responseWithError, true], + [{ ...responseWithError, id: '1' }, true], ]; export const isResponseWithNotificationValidTest: [JsonRpcNotification, boolean][] = [ @@ -63,4 +66,41 @@ export const toPayloadValidTest: [any, any][] = [ params: undefined, }, ], + [ + { method: 'add', jsonrpc: '1.0', id: 1 }, + { + method: 'add', + id: 1, + jsonrpc: '1.0', + params: undefined, + }, + ], +]; + +export const isResponseRpcErrorValidData: [any, boolean][] = [ + [responseWithRpcError, true], + [responseWithError, false], +]; + +export const isBatchRequestValidData: [any, boolean][] = [ + [ + [ + { + method: 'add', + id: 1, + jsonrpc: '1.0', + params: undefined, + }, + ], + true, + ], + [ + { + method: 'add', + id: 1, + jsonrpc: '1.0', + params: undefined, + }, + false, + ], ]; diff --git a/packages/web3-utils/test/fixtures/string_manipulation.ts b/packages/web3-utils/test/fixtures/string_manipulation.ts index be5b298c803..dde49247677 100644 --- a/packages/web3-utils/test/fixtures/string_manipulation.ts +++ b/packages/web3-utils/test/fixtures/string_manipulation.ts @@ -58,7 +58,7 @@ export const padRightData: [[Numbers, number, string], HexString][] = [ [['15.5', 8, '0'], '15.50000'], ]; -export const toTwosComplementData: [[Numbers, number], HexString][] = [ +export const toTwosComplementData: [[Numbers, number | undefined], HexString][] = [ [[13, 32], '0x0000000000000000000000000000000d'], [[256, 30], '0x000000000000000000000000000100'], [[0, 32], '0x00000000000000000000000000000000'], @@ -69,9 +69,10 @@ export const toTwosComplementData: [[Numbers, number], HexString][] = [ [['13', 32], '0x0000000000000000000000000000000d'], [['-13', 32], '0xfffffffffffffffffffffffffffffff3'], [[-16, 2], '0xf0'], + [['0x1', undefined], '0x0000000000000000000000000000000000000000000000000000000000000001'], ]; -export const fromTwosComplementData: [[Numbers, number], number | bigint][] = [ +export const fromTwosComplementData: [[Numbers, number | undefined], number | bigint][] = [ [['0x0000000000000000000000000000000d', 32], 13], [['0x000000000000000000000000000100', 30], 256], [['0x00000000000000000020000000000000', 32], BigInt('9007199254740992')], @@ -81,6 +82,7 @@ export const fromTwosComplementData: [[Numbers, number], number | bigint][] = [ [[1000, 64], 1000], [[-1000, 64], -1000], [[BigInt(9), 1], -7], + [['0x0000000000000000000000000000000000000000000000000000000000000001', undefined], 1], ]; export const toTwosComplementInvalidData: [[Numbers, number], string][] = [ diff --git a/packages/web3-utils/test/unit/chunk_response_parser.test.ts b/packages/web3-utils/test/unit/chunk_response_parser.test.ts index 22100a3e6a8..bb4c70e8f1b 100644 --- a/packages/web3-utils/test/unit/chunk_response_parser.test.ts +++ b/packages/web3-utils/test/unit/chunk_response_parser.test.ts @@ -71,4 +71,18 @@ describe('chunk_response_parser', () => { }), ); }); + + it('lastChunkTimeout return empty when auto reconnect true', async () => { + const p = new ChunkResponseParser(eventEmiter, true); + // @ts-expect-error set private property + p.chunkTimeout = 10; + const result = p.parseResponse( + '{"jsonrpc":"2.0","id":"96aa3f13-077c-4c82-a64a-64b8626f8192","result":"0x141414141', + ); + const onError = jest.fn(); + eventEmiter.on('error', onError); + // eslint-disable-next-line no-promise-executor-return + await new Promise(resolve => setTimeout(resolve, 1000)); + expect(result).toEqual([]); + }); }); diff --git a/packages/web3-utils/test/unit/converters.test.ts b/packages/web3-utils/test/unit/converters.test.ts index 940590f06e7..84073f4a4d7 100644 --- a/packages/web3-utils/test/unit/converters.test.ts +++ b/packages/web3-utils/test/unit/converters.test.ts @@ -15,6 +15,9 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ +import { InvalidBytesError } from 'web3-errors'; +import { validator, utils } from 'web3-validator'; + import { asciiToHex, bytesToHex, @@ -325,6 +328,16 @@ describe('converters', () => { it.each(toHexValidData)('%s', (input, output) => { expect(toHex(input, true)).toEqual(output[1]); }); + + it('an interesting case that needs investigation', () => { + // TODO: This case is to be investigated further + expect( + toHex( + '101611154195520776335741463917853444671577865378275924493376429267637792638729', + true, + ), + ).toBe('uint'); + }); }); describe('invalid cases', () => { @@ -341,6 +354,14 @@ describe('converters', () => { }); describe('fromWei', () => { + beforeEach(() => { + jest.spyOn(console, 'warn').mockImplementation(() => { + // do nothing + }); + }); + afterAll(() => { + jest.restoreAllMocks(); + }); describe('valid cases', () => { it.each(fromWeiValidData)('%s', (input, output) => { expect(fromWei(input[0], input[1])).toEqual(output); @@ -372,13 +393,14 @@ describe('converters', () => { // do nothing }); }); + afterAll(() => { + jest.restoreAllMocks(); + }); it.each(toWeiValidDataWarnings)('%s', (input, output) => { toWei(input[0], input[1]); - // expect(() => toWei(input[0], input[1])).toThrow(output); - expect(console.warn).toHaveBeenCalledWith(output) + expect(console.warn).toHaveBeenCalledWith(output); }); - - }) + }); }); describe('toChecksumAddress', () => { describe('valid cases', () => { @@ -391,6 +413,33 @@ describe('converters', () => { expect(() => toChecksumAddress(input)).toThrow(output); }); }); + it('should return an empty string if hash is nullish', () => { + const address = '0xc1912fee45d61c87cc5ea59dae31190fffff232d'; + + // mock utils.uint8ArrayToHexString to return an empty string + jest.mock('web3-validator'); + jest.spyOn(utils, 'uint8ArrayToHexString').mockReturnValue( + undefined as unknown as string, + ); + + const result = toChecksumAddress(address); + expect(result).toBe(''); + + jest.mock('web3-validator').restoreAllMocks(); + }); + + it('should return an empty string if hash is equal to "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"', () => { + const address = '0xc1912fee45d61c87cc5ea59dae31190fffff232d'; + + // mock utils.uint8ArrayToHexString to return '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' + jest.mock('web3-validator'); + const hash = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; + jest.spyOn(utils, 'uint8ArrayToHexString').mockReturnValue(hash); + const result = toChecksumAddress(address); + expect(result).toBe(''); + + jest.mock('web3-validator').restoreAllMocks(); + }); }); describe('bytesToUint8Array', () => { describe('bytesToUint8Array', () => { @@ -404,6 +453,18 @@ describe('converters', () => { it.each(bytesToUint8ArrayInvalidData)('%s', (input, output) => { expect(() => bytesToUint8Array(input)).toThrow(output); }); + + it('should throw InvalidBytesError for invalid input even if it passed the validator', () => { + const invalidData = 8; + // the package 'web3-validator' contains `validator`. + // Mock mock the `validator.validate(...)` to not throw an error, but return `false` instead. + jest.mock('web3-validator'); + + jest.spyOn(validator, 'validate').mockReturnValue(undefined); + + expect(() => bytesToUint8Array(invalidData as any)).toThrow(InvalidBytesError); + jest.mock('web3-validator').restoreAllMocks(); + }); }); }); }); diff --git a/packages/web3-utils/test/unit/formatter.test.ts b/packages/web3-utils/test/unit/formatter.test.ts index bed8b55de8e..aa1a14fb6c9 100644 --- a/packages/web3-utils/test/unit/formatter.test.ts +++ b/packages/web3-utils/test/unit/formatter.test.ts @@ -24,9 +24,10 @@ import { HexString, Numbers, } from 'web3-types'; +import { FormatterError } from 'web3-errors'; import { expectTypeOf, typecheck } from '@humeris/espresso-shot'; import { isDataFormatValid, convertScalarValueValid } from '../fixtures/formatter'; -import { format, isDataFormat, convertScalarValue } from '../../src/formatter'; +import { format, isDataFormat, convertScalarValue, convert } from '../../src/formatter'; import { hexToBytes } from '../../src/converters'; type TestTransactionInfoType = { @@ -738,7 +739,6 @@ describe('formatter', () => { ).toEqual(result); }); }); - describe('object values', () => { it('should format simple object', () => { const schema = { @@ -776,6 +776,13 @@ describe('formatter', () => { expect(result).toEqual(expected); }); + it('should throw FormatterError when jsonSchema is invalid', () => { + const invalidSchema1 = {}; + const data = { key: 'value' }; + + expect(() => format(invalidSchema1, data)).toThrow(FormatterError); + }); + it('should format nested objects', () => { const schema = { type: 'object', @@ -846,4 +853,16 @@ describe('formatter', () => { }); }); }); + + describe('convert', () => { + it('should return empty when no properties or items', () => { + const data = { key: 'value' }; + const schema = { + type: 'object', + }; + const f = { number: FMT_NUMBER.NUMBER, bytes: FMT_BYTES.HEX }; + const result = convert(data, schema, [], f, []); + expect(result).toEqual({}); + }); + }); }); diff --git a/packages/web3-utils/test/unit/hash.test.ts b/packages/web3-utils/test/unit/hash.test.ts index d381e3c4240..814dacd45f2 100644 --- a/packages/web3-utils/test/unit/hash.test.ts +++ b/packages/web3-utils/test/unit/hash.test.ts @@ -23,6 +23,7 @@ import { soliditySha3Raw, encodePacked, keccak256 as web3keccak256, + getStorageSlotNumForLongString, } from '../../src/hash'; import { sha3Data, @@ -37,6 +38,7 @@ import { encodePackedInvalidData, keccak256ValidData, soliditySha3BigIntValidData, + getStorageSlotNumForLongStringValidData, } from '../fixtures/hash'; describe('hash', () => { @@ -149,4 +151,10 @@ describe('hash', () => { }); }); }); + + describe('getStorageSlotNumForLongString', () => { + it.each(getStorageSlotNumForLongStringValidData)('%s', (input, output) => { + expect(getStorageSlotNumForLongString(input)).toEqual(output); + }); + }); }); diff --git a/packages/web3-utils/test/unit/index.test.ts b/packages/web3-utils/test/unit/index.test.ts new file mode 100644 index 00000000000..8682408801a --- /dev/null +++ b/packages/web3-utils/test/unit/index.test.ts @@ -0,0 +1,64 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import * as web3Utils from '../../src'; + +import * as converters from '../../src/converters.js'; +import * as eventEmitter from '../../src/event_emitter.js'; +import * as validation from '../../src/validation.js'; +import * as formatter from '../../src/formatter.js'; +import * as hash from '../../src/hash.js'; +import * as random from '../../src/random.js'; +import * as stringManipulation from '../../src/string_manipulation.js'; +import * as objects from '../../src/objects.js'; +import * as promiseHelpers from '../../src/promise_helpers.js'; +import * as jsonRpc from '../../src/json_rpc.js'; +import * as web3DeferredPromise from '../../src/web3_deferred_promise.js'; +import * as ChunkResponseParser from '../../src/chunk_response_parser.js'; +import * as uuid from '../../src/uuid.js'; +import * as web3Eip1193Provider from '../../src/web3_eip1193_provider.js'; +import * as socketProvider from '../../src/socket_provider.js'; +import * as uint8array from '../../src/uint8array.js'; + +describe('web3-utils exports', () => { + it('should export all modules', () => { + const modules = [ + converters, + eventEmitter, + validation, + formatter, + hash, + random, + stringManipulation, + objects, + promiseHelpers, + jsonRpc, + web3DeferredPromise, + ChunkResponseParser, + uuid, + web3Eip1193Provider, + socketProvider, + uint8array, + ]; + + modules.forEach(module => { + Object.keys(module).forEach((property: string | any[]) => { + expect(web3Utils).toHaveProperty(property); + }); + }); + }); +}); diff --git a/packages/web3-utils/test/unit/json_rpc.test.ts b/packages/web3-utils/test/unit/json_rpc.test.ts index 89261009916..ea16cd646d1 100644 --- a/packages/web3-utils/test/unit/json_rpc.test.ts +++ b/packages/web3-utils/test/unit/json_rpc.test.ts @@ -16,22 +16,28 @@ along with web3.js. If not, see . */ import { + isResponseRpcError, isResponseWithResult, isResponseWithError, isResponseWithNotification, isSubscriptionResult, isValidResponse, isBatchResponse, + setRequestIdStart, + toBatchPayload, + isBatchRequest, toPayload, } from '../../src/json_rpc'; import { isResponseWithResultValidTest, isResponseWithErrorValidTest, + isResponseRpcErrorValidData, isResponseWithNotificationValidTest, isSubscriptionResultValidTest, toPayloadValidTest, isValidResponseValidTest, isBatchResponseValidTest, + isBatchRequestValidData, } from '../fixtures/json_rpc'; describe('json rpc tests', () => { @@ -51,6 +57,14 @@ describe('json rpc tests', () => { }); }); }); + describe('isResponseRpcError', () => { + describe('valid cases', () => { + it.each(isResponseRpcErrorValidData)('%s', (input, output) => { + const result = isResponseRpcError(input); + expect(result).toBe(output); + }); + }); + }); describe('isResponseWithNotification', () => { describe('valid cases', () => { it.each(isResponseWithNotificationValidTest)('should have notify', (input, output) => { @@ -77,18 +91,57 @@ describe('json rpc tests', () => { }); describe('isBatchResponseValid', () => { describe('valid cases', () => { - it.each(isBatchResponseValidTest)('isValidresponse valid test', (input, output) => { - const result = isBatchResponse(input); - expect(result).toBe(output); + it.each(isBatchResponseValidTest)( + 'isBatchResponseValid valid test', + (input, output) => { + const result = isBatchResponse(input); + expect(result).toBe(output); + }, + ); + }); + }); + describe('isBatchRequest', () => { + describe('valid cases', () => { + it.each(isBatchRequestValidData)('isBatchRqeuest valid data', (input, output) => { + expect(isBatchRequest(input)).toBe(output); }); }); }); describe('toPayloadValid', () => { describe('valid cases', () => { - it.each(toPayloadValidTest)('isValidresponse valid test', (input, output) => { - const result = toPayload(input); + beforeEach(() => { + setRequestIdStart(undefined); + }); + it.each(toPayloadValidTest)('toPayload valid test', async (input, output) => { + const result = await new Promise(resolve => { + resolve(toPayload(input)); + }); expect(result).toStrictEqual(output); }); + it('should give payload that has requestid set', async () => { + setRequestIdStart(1); + const result = await new Promise(resolve => { + resolve(toPayload({ method: 'delete' })); + }); + expect(result).toStrictEqual({ + method: 'delete', + id: 2, + params: undefined, + jsonrpc: '2.0', + }); + }); + }); + }); + describe('toBatchPayload', () => { + it('should batch payload', async () => { + setRequestIdStart(0); + const result = await new Promise(resolve => { + resolve(toBatchPayload([{ method: 'delete' }, { method: 'add' }])); + }); + expect(result).toStrictEqual([ + { method: 'delete', id: 1, params: undefined, jsonrpc: '2.0' }, + { method: 'add', id: 2, params: undefined, jsonrpc: '2.0' }, + ]); }); }); }); diff --git a/packages/web3-utils/test/unit/objects.test.ts b/packages/web3-utils/test/unit/objects.test.ts index 1201b3b7345..cca9d46cba9 100644 --- a/packages/web3-utils/test/unit/objects.test.ts +++ b/packages/web3-utils/test/unit/objects.test.ts @@ -79,5 +79,14 @@ describe('objects', () => { expect(result.a).toStrictEqual(new Uint8Array([1, 2])); }); + + it('should return the destination object if it is not iterable', () => { + const destination = 123; // Replace with your desired destination object + const sources: Record[] = []; // Replace with your desired sources array + + const result = mergeDeep(destination as unknown as Record, ...sources); + + expect(result).toBe(destination); + }); }); }); diff --git a/packages/web3-utils/test/unit/promise_helpers.test.ts b/packages/web3-utils/test/unit/promise_helpers.test.ts index 7492c51fc24..14ccc00488d 100644 --- a/packages/web3-utils/test/unit/promise_helpers.test.ts +++ b/packages/web3-utils/test/unit/promise_helpers.test.ts @@ -60,6 +60,14 @@ describe('promise helpers', () => { new Error('time out'), ); }); + it('throws if result is an instance of Error', async () => { + const dummyError = new Error('dummy error'); + const asyncHelper = async () => { + return dummyError; + }; + + await expect(waitWithTimeout(asyncHelper(), 1000)).rejects.toThrow(dummyError); + }); }); describe('rejectIfTimeout', () => { it('%s', async () => { diff --git a/packages/web3-utils/test/unit/socket_provider.test.ts b/packages/web3-utils/test/unit/socket_provider.test.ts index a09f1467ce0..c2c3756c755 100644 --- a/packages/web3-utils/test/unit/socket_provider.test.ts +++ b/packages/web3-utils/test/unit/socket_provider.test.ts @@ -15,7 +15,14 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { Web3APIPayload, EthExecutionAPI, JsonRpcResponse, Web3ProviderStatus } from 'web3-types'; +import { + Web3APIPayload, + EthExecutionAPI, + JsonRpcResponse, + Web3ProviderStatus, + JsonRpcIdentifier, +} from 'web3-types'; +import { MaxAttemptsReachedOnReconnectingError, InvalidClientError } from 'web3-errors'; import { EventEmitter } from '../../src/event_emitter'; // eslint-disable-next-line import/no-relative-packages import { sleep } from '../../../../fixtures/utils'; @@ -40,8 +47,27 @@ class TestProvider extends SocketProvider { // eslint-disable-next-line protected _sendToSocket(_payload: Web3APIPayload): void {} // eslint-disable-next-line - protected _parseResponses(_event: any): JsonRpcResponse[] { - return [] as JsonRpcResponse[]; + protected _parseResponses(_event: { data: string } | undefined): JsonRpcResponse[] { + if (!_event || !_event.data) { + return []; + } + const returnValues: JsonRpcResponse[] = []; + + // DE-CHUNKER + const dechunkedData = _event.data + .replace(/\}[\n\r]?\{/g, '}|--|{') // }{ + .replace(/\}\][\n\r]?\[\{/g, '}]|--|[{') // }][{ + .replace(/\}[\n\r]?\[\{/g, '}|--|[{') // }[{ + .replace(/\}\][\n\r]?\{/g, '}]|--|{') // }]{ + .split('|--|'); + + dechunkedData.forEach((chunkData: string) => { + const result = JSON.parse(chunkData) as unknown as JsonRpcResponse; + + if (result) returnValues.push(result); + }); + + return returnValues; } public message(_event: any): void { this._onMessage(_event); @@ -74,6 +100,32 @@ describe('SocketProvider', () => { expect(provider).toBeInstanceOf(SocketProvider); expect(provider.SocketConnection).toEqual(dummySocketConnection); }); + it('should call _clearQueues when chunkResponseParser emits an error', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const clearQueuesSpy = jest.spyOn(provider as any, '_clearQueues'); + + try { + // @ts-expect-error access readonly method + provider['chunkResponseParser']['autoReconnect'] = false; + // @ts-expect-error access readonly method + provider['chunkResponseParser']['chunkTimeout'] = 0; + + provider['chunkResponseParser'].parseResponse('invalid-json'); + } catch (error) { + // nothing + } + + // wait 1 second for the timeout to trigger + await sleep(100); + + expect(clearQueuesSpy).toHaveBeenCalled(); + }); + it('should error when failing to _validateProviderPath', () => { + expect(() => { + // eslint-disable-next-line no-new + new TestProvider('', socketOption, { delay: 0 }); + }).toThrow(InvalidClientError); + }); }); describe('testing _reconnect() method', () => { it('should not be called when { autoReconnect: false }', () => { @@ -94,6 +146,111 @@ describe('SocketProvider', () => { // @ts-expect-error run protected method expect(provider._reconnect).not.toHaveBeenCalled(); }); + it('should call _reconnect when isReconnecting is true and an error happens', () => { + const provider = new TestProvider(socketPath, socketOption); + provider['_reconnect'] = jest.fn(); + provider['isReconnecting'] = true; + + provider['_onError']({}); + + expect(provider['_reconnect']).toHaveBeenCalled(); + }); + + it('should call _reconnect when isReconnecting is false and an error happens', () => { + const provider = new TestProvider(socketPath, socketOption); + provider['_reconnect'] = jest.fn(); + provider['isReconnecting'] = false; + + provider['_onError']({}); + expect(provider['_reconnect']).not.toHaveBeenCalled(); + }); + + it('should return if the provider is already isReconnecting', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + // just to run the test faster moke `connect` + jest.spyOn(provider, 'connect'); + + // @ts-expect-error access protected method + expect(provider._reconnectAttempts).toBe(0); + provider['_reconnect'](); + // @ts-expect-error access protected method + expect(provider._reconnectAttempts).toBe(1); + + // after the first call provider.isReconnecting will set to true and so the `_reconnectAttempts` will not be incremented + provider['_reconnect'](); + + // @ts-expect-error access protected method + expect(provider._reconnectAttempts).toBe(1); + }); + + it('should reconnect the socket when the number of reconnect attempts is less than the maximum attempts', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + // @ts-expect-error access protected method + const openSocketConnectionSpy = jest.spyOn(provider, '_openSocketConnection'); + // @ts-expect-error access protected method + const removeSocketListenersSpy = jest.spyOn(provider, '_removeSocketListeners'); + const connectSpy = jest.spyOn(provider, 'connect'); + + // Set the reconnect attempts to less than the maximum attempts + provider['_reconnectAttempts'] = 2; + + provider['_reconnect'](); + + // wait for the timeout to trigger + await sleep(100); + + expect(openSocketConnectionSpy).toHaveBeenCalled(); + expect(removeSocketListenersSpy).toHaveBeenCalled(); + expect(connectSpy).toHaveBeenCalled(); + }); + + it('should clear the queues and emit an error event when the number of reconnect attempts reaches the maximum attempts', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const clearQueuesSpy = jest.spyOn(provider as any, '_clearQueues'); + // @ts-expect-error access protected method + const removeSocketListenersSpy = jest.spyOn(provider, '_removeSocketListeners'); + const errorEventSpy = jest.spyOn(provider['_eventEmitter'], 'emit'); + + // Set the reconnect attempts to the maximum attempts + provider['_reconnectAttempts'] = 5; + + provider['_reconnect'](); + + // wait for the timeout to trigger + await sleep(100); + + expect(clearQueuesSpy).toHaveBeenCalled(); + expect(removeSocketListenersSpy).toHaveBeenCalled(); + expect(errorEventSpy).toHaveBeenCalledWith( + 'error', + expect.any(MaxAttemptsReachedOnReconnectingError), + ); + }); + + it('should keep pending requests but clear the sent requests queue when reconnecting', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + provider.setStatus('connected'); + // Add a sent request + provider.request({ id: 2, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + // @ts-expect-error run protected method + expect(provider._sentRequestsQueue.size).toBe(1); + + // @ts-expect-error access protected method + const rejectSpy = jest.spyOn(provider['_pendingRequestsQueue'], 'delete'); + const deleteSpy = jest.spyOn(provider['_sentRequestsQueue'], 'delete'); + + const pendingRequestsQueueSize = provider['_pendingRequestsQueue'].size; + const sentRequestsQueueSize = provider['_sentRequestsQueue'].size; + + provider['_reconnect'](); + + expect(provider['_pendingRequestsQueue'].size).toEqual(pendingRequestsQueueSize); + + expect(deleteSpy).toHaveBeenCalledTimes(sentRequestsQueueSize); + }); }); describe('testing connect() method', () => { @@ -298,6 +455,46 @@ describe('SocketProvider', () => { // @ts-expect-error run protected method expect(provider._sentRequestsQueue.get(payload.id).payload).toBe(payload); }); + + it('should add request to the `_sentRequestsQueue` when the status is `connected` for batch requests', () => { + const provider = new TestProvider(socketPath, socketOption); + const payload = [ + { id: 1, method: 'some_rpc_method', jsonrpc: '2.0' as JsonRpcIdentifier }, + { id: 2, method: 'some_rpc_method', jsonrpc: '2.0' as JsonRpcIdentifier }, + ]; + provider.setStatus('connected'); + const reqPromise = provider.request(payload as any); + expect(reqPromise).toBeInstanceOf(Promise); + + // the id of the first request in the batch is the one used to identify the batch request + // @ts-expect-error run protected method + expect(provider._sentRequestsQueue.get(payload[0].id).payload).toBe(payload); + }); + + it('should clear _sentRequestsQueue in case `_sendToSocket` had an error', async () => { + // Create a mock SocketProvider instance + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + const deleteSpy = jest.spyOn(provider['_sentRequestsQueue'], 'delete'); + + provider.setStatus('connected'); + // Assert that the _sendToSocket method was called with the correct payload + // @ts-expect-error access protected method + provider._sendToSocket = () => { + throw new Error('any error'); + }; + // Call the request method + provider + .request({ id: 1, method: 'some_rpc_method' }) + .then(() => { + // nothing + }) + .catch(() => { + // nothing + }); + + expect(deleteSpy).toHaveBeenCalled(); + }); }); describe('testing _clearQueues() method', () => { @@ -339,4 +536,330 @@ describe('SocketProvider', () => { }); }); }); + + describe('safeDisconnect', () => { + it('should disconnect the socket when there are no pending or sent requests', async () => { + const provider = new TestProvider(socketPath, socketOption); + const disconnectSpy = jest.spyOn(provider, 'disconnect'); + await provider.safeDisconnect(); + expect(disconnectSpy).toHaveBeenCalled(); + }); + + it('should disconnect the socket after waiting for pending and sent requests to be empty', async () => { + const provider = new TestProvider(socketPath, socketOption); + const disconnectSpy = jest.spyOn(provider, 'disconnect'); + + // Add a pending request + provider.request({ id: 1, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + // Add a sent request + provider.request({ id: 2, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + expect(provider.getPendingRequestQueueSize()).toBe(2); + + provider.clearQueues(); + // Call safeDisconnect and wait for the queues to be empty + await provider.safeDisconnect(undefined, undefined, false, 100); + + expect(disconnectSpy).toHaveBeenCalled(); + expect(provider.getPendingRequestQueueSize()).toBe(0); + expect(provider.getSentRequestsQueueSize()).toBe(0); + }); + + it('should force disconnect the socket after waiting for 5 attempts', async () => { + const provider = new TestProvider(socketPath, socketOption); + const disconnectSpy = jest.spyOn(provider, 'disconnect'); + const clearQueuesSpy = jest.spyOn(provider as any, 'clearQueues'); + + // Add a pending request + provider.request({ id: 1, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + expect(provider.getPendingRequestQueueSize()).toBe(1); + + // Add a sent request + provider.request({ id: 2, method: 'some_rpc_method' }).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + // expect(provider.getSentRequestsQueueSize()).toBe(1); + + // Call safeDisconnect with forceDisconnect set to true and a small interval + await provider.safeDisconnect(undefined, undefined, true, 100); + + expect(disconnectSpy).toHaveBeenCalled(); + expect(clearQueuesSpy).toHaveBeenCalled(); + }); + }); + describe('removeAllListeners', () => { + it('should remove all listeners for the specified event type', () => { + const provider = new TestProvider(socketPath, socketOption); + const listener1 = jest.fn(); + const listener2 = jest.fn(); + const listener3 = jest.fn(); + provider.on('event', listener1); + provider.on('event', listener2); + provider.on('otherEvent', listener3); + + provider.removeAllListeners('event'); + + provider['_eventEmitter'].emit('event'); + provider['_eventEmitter'].emit('otherEvent'); + + expect(listener1).not.toHaveBeenCalled(); + expect(listener2).not.toHaveBeenCalled(); + expect(listener3).toHaveBeenCalled(); + }); + }); + + describe('_sendPendingRequests', () => { + it('should send pending requests to the socket', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + const payload1 = { id: 1, method: 'method1', params: [] }; + const payload2 = { id: 2, method: 'method2', params: [] }; + // Add a pending request + provider.request(payload1).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + // Add a sent request + provider.request(payload2).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + expect(provider.getPendingRequestQueueSize()).toBe(2); + + provider['_sendToSocket'] = jest.fn(); + + provider['_sendPendingRequests'](); + + expect(provider['_sendToSocket']).toHaveBeenCalledTimes(2); + expect(provider['_sendToSocket']).toHaveBeenCalledWith(payload1); + expect(provider['_sendToSocket']).toHaveBeenCalledWith(payload2); + expect(provider['_pendingRequestsQueue'].size).toBe(0); + expect(provider['_sentRequestsQueue'].size).toBe(2); + }); + + it('should not send any requests if the pending requests queue is empty', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + provider['_sendToSocket'] = jest.fn(); + + provider['_sendPendingRequests'](); + + expect(provider['_sendToSocket']).not.toHaveBeenCalled(); + expect(provider['_pendingRequestsQueue'].size).toBe(0); + expect(provider['_sentRequestsQueue'].size).toBe(0); + }); + }); + + describe('_onConnect', () => { + beforeEach(() => { + jest.spyOn(console, 'error').mockImplementation(() => { + // do nothing + }); // Spy on console.error to suppress and check calls + }); + + afterEach(() => { + jest.restoreAllMocks(); // Restore all mocks after each test + }); + + it('should set the connection status to "connected"', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + // Act + provider['_onConnect'](); + + expect(provider['_connectionStatus']).toBe('connected'); + }); + it('should set _accounts and _chainId when _getAccounts and _getChainId resolve', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, '_getAccounts').mockResolvedValueOnce([123]); + jest.spyOn(provider as any, '_getChainId').mockResolvedValueOnce('1'); + + await new Promise(resolve => { + provider['_onConnect'](); + resolve(''); + }); + expect((provider as any)._chainId).toBe('1'); + expect((provider as any)._accounts).toEqual([123]); + }); + it('chainID should change when connecting twice', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + await new Promise(resolve => { + jest.spyOn(provider as any, '_getAccounts').mockResolvedValueOnce([123]); + jest.spyOn(provider as any, '_getChainId').mockResolvedValueOnce('1'); + provider['_onConnect'](); + resolve(''); + }); + expect((provider as any)._chainId).toBe('1'); + expect((provider as any)._accounts).toEqual([123]); + + await new Promise(resolve => { + jest.spyOn(provider as any, '_getAccounts').mockResolvedValueOnce([123]); + jest.spyOn(provider as any, '_getChainId').mockResolvedValueOnce('2'); + provider['_onConnect'](); + resolve(''); + }); + expect((provider as any)._chainId).toBe('2'); + expect((provider as any)._accounts).toEqual([123]); + }); + it('should catch errors when _getAccounts and _getChainId throws', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, '_getChainId').mockRejectedValueOnce(new Error('')); + jest.spyOn(provider as any, '_getAccounts').mockRejectedValueOnce(new Error('')); + jest.spyOn(provider, 'request').mockReturnValue(new Error() as unknown as Promise); + + await new Promise(resolve => { + provider['_onConnect'](); + resolve(''); + }); + expect((provider as any)._chainId).toBe(''); + expect((provider as any)._accounts).toEqual([]); + }); + it('should catch when connect emit fails', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, '_getChainId').mockResolvedValueOnce(1); + jest.spyOn(provider as any, '_getAccounts').mockResolvedValueOnce([]); + (provider as any)._eventEmitter.emit = jest.fn(() => { + throw new Error('event emitter failed'); + }); + + await new Promise(resolve => { + provider['_onConnect'](); + resolve(''); + }); + // I would check if console.error is called, but facing a race condition + expect((provider as any)._eventEmitter.emit).toHaveBeenCalledTimes(1); + }); + }); + + describe('_getChainId', () => { + it('should return data from the chainId method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const chainId = 1; + jest.spyOn(provider as any, 'request').mockResolvedValueOnce({ result: chainId }); + const result = await provider['_getChainId'](); + expect(result).toBe(chainId); + }); + + it('should be returning undefined from the chainId method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, 'request').mockResolvedValueOnce({ result: undefined }); + const result = await provider['_getChainId'](); + expect(result).toBe(''); + }); + + it('should return empty from the chainId method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, 'request').mockResolvedValueOnce(undefined); + const result = await provider['_getChainId'](); + expect(result).toBe(''); + }); + }); + + describe('_getAccounts', () => { + it('should return data from the _getAccounts method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const accounts = [1]; + jest.spyOn(provider as any, 'request').mockResolvedValueOnce({ result: accounts }); + const result = await provider['_getAccounts'](); + expect(result).toBe(accounts); + }); + + it('should returning undefined from the _getAccounts method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, 'request').mockResolvedValueOnce({ result: undefined }); + const result = await provider['_getAccounts'](); + expect(result).toEqual([]); + }); + + it('should return empty from the _getAccounts method', async () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + jest.spyOn(provider as any, 'request').mockResolvedValueOnce(undefined); + const result = await provider['_getAccounts'](); + expect(result).toEqual([]); + }); + }); + + describe('_onMessage', () => { + it('should resolve the deferred promise for valid responses with errors', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + + const payload1 = { + id: 1, + method: 'method1', + params: [], + jsonrpc: '2.0' as JsonRpcIdentifier, + error: { code: -32601, message: 'Method not found' }, + }; + const event = { + data: JSON.stringify(payload1), + }; + // Add a pending request + provider.request(payload1).catch(() => { + // it will throw with "Connection not open" because no actual connection is used in the test. So ignore the error + }); + expect(provider.getPendingRequestQueueSize()).toBe(1); + + // @ts-expect-error access protected method + provider['_sentRequestsQueue'] = provider['_pendingRequestsQueue']; + + const deferredPromiseResolveSpy = jest.spyOn( + provider['_sentRequestsQueue'].get(1)!.deferredPromise, + 'resolve', + ); + provider['_onMessage']({ + ...event, + }); + + expect(deferredPromiseResolveSpy).toHaveBeenCalledWith(payload1); + }); + + it('should not emit "message" event for invalid responses', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const event = { + data: JSON.stringify([ + { id: 1, jsonrpc: '2.0', error: { code: -32601, message: 'Method not found' } }, + { id: 2, jsonrpc: '2.0', error: { code: -32601, message: 'Method not found' } }, + ]), + }; + + const eventEmitterSpy = jest.spyOn(provider['_eventEmitter'], 'emit'); + + provider['_onMessage'](event); + + expect(eventEmitterSpy).not.toHaveBeenCalledWith('message', { + id: 1, + jsonrpc: '2.0', + error: { code: -32601, message: 'Method not found' }, + }); + expect(eventEmitterSpy).not.toHaveBeenCalledWith('message', { + id: 2, + jsonrpc: '2.0', + error: { code: -32601, message: 'Method not found' }, + }); + }); + + it('should emit "message" event for notifications', () => { + const provider = new TestProvider(socketPath, socketOption, { delay: 0 }); + const event = { + data: JSON.stringify({ + jsonrpc: '2.0', + method: 'notification_1_subscription', + params: {}, + }), + }; + + const eventEmitterSpy = jest.spyOn(provider['_eventEmitter'], 'emit'); + + provider['_onMessage'](event); + + expect(eventEmitterSpy).toHaveBeenCalledWith('message', { + jsonrpc: '2.0', + method: 'notification_1_subscription', + params: {}, + }); + }); + }); }); diff --git a/packages/web3-utils/test/unit/web3_deferred_promise.test.ts b/packages/web3-utils/test/unit/web3_deferred_promise.test.ts index b8180705969..6fe87129e73 100644 --- a/packages/web3-utils/test/unit/web3_deferred_promise.test.ts +++ b/packages/web3-utils/test/unit/web3_deferred_promise.test.ts @@ -53,4 +53,17 @@ describe('Web3DeferredPromise', () => { expect(promise.state).toBe('rejected'); }); }); + + describe('Web3DeferredPromise finally', () => { + it('should execute the callback when the promise is settled', async () => { + const promise = new Web3DeferredPromise(); + let callbackExecuted = false; + promise.resolve(1); + await promise.finally(() => { + callbackExecuted = true; + }); + + expect(callbackExecuted).toBe(true); + }); + }); }); From a7d67c6a08c06fd474ebe9eb5e0a9c516dffb50c Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Tue, 4 Jun 2024 08:30:30 -0700 Subject: [PATCH 13/25] Formatting fixes for recently updated pages (#7072) --- .../guides/getting_started/introduction.md | 4 +- .../docs/guides/getting_started/quickstart.md | 75 +++++++++--------- .../docs/guides/web3_providers_guide/index.md | 77 +++++++++---------- 3 files changed, 79 insertions(+), 77 deletions(-) diff --git a/docs/docs/guides/getting_started/introduction.md b/docs/docs/guides/getting_started/introduction.md index 0e92051b4ce..c32338d324d 100644 --- a/docs/docs/guides/getting_started/introduction.md +++ b/docs/docs/guides/getting_started/introduction.md @@ -49,7 +49,7 @@ Web3.js is a modular collection of packages, each of which serves a specific nee - [**Iban:**](/libdocs/Iban) The `web3-eth-iban` package allows you to switch between **Ethereum addresses and special banking-like addresses** (IBAN or BBAN) and simplifies conversion between the types. -### Additional supporting packages +### Additional Supporting Packages - [**Web3 Core:**](/api/web3-core) subscriptions, request management, and configuration used by other Web3 packages @@ -61,7 +61,7 @@ Web3.js is a modular collection of packages, each of which serves a specific nee - [**Web3 RPC Methods:**](/api/web3/namespace/rpcMethods) functions for making RPC requests to Ethereum using a given provider -## Advantages over other libraries +## Advantages Over Other Libraries - **Extensive Documentation and Community**: Web3.js is one of the most established Ethereum libraries, which means it benefits from extensive documentation and a large, active community. Web3.js is widely adopted and has been thoroughly tested in various production environments, and is compatible with a broad range of other tools and services in the Ethereum ecosystem. diff --git a/docs/docs/guides/getting_started/quickstart.md b/docs/docs/guides/getting_started/quickstart.md index 886b2690e19..80551ad735b 100644 --- a/docs/docs/guides/getting_started/quickstart.md +++ b/docs/docs/guides/getting_started/quickstart.md @@ -7,7 +7,7 @@ sidebar_label: Quickstart Use the live code editor to try Web3.js in your browser now! Keep reading to learn how to use Web3.js in a local development environment. -## Live code editor +## Live Code Editor @@ -41,7 +41,7 @@ For ESM-style imports, use: import { Web3 } from 'web3'; ``` -## Initialize `Web3` with a provider +## Initialize `Web3` with a Provider [Providers](/guides/web3_providers_guide/) are services that are responsible for enabling connectivity with the Ethereum network. The `Web3` object must be initialized with a valid provider to function as intended. Web3.js supports [HTTP](/guides/web3_providers_guide/#http-provider), [WebSocket](/guides/web3_providers_guide/#websocket-provider), and [IPC](/guides/web3_providers_guide/#ipc-provider) providers, and exposes packages for working with each type of provider. @@ -50,16 +50,16 @@ Web3.js is in compliance with [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193 ``` ts import { Web3 } from 'web3'; -//private RPC endpoint +// private RPC endpoint const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); -//or public RPC endpoint -//const web3 = new Web3('https://eth.llamarpc.com'); +// or public RPC endpoint +// const web3 = new Web3('https://eth.llamarpc.com'); web3.eth.getBlockNumber().then(console.log); // ↳ 18849658n ``` -## Querying the blockchain +## Querying the Blockchain After instantiating the `Web3` instance with a provider, the [`web3-eth`](/libdocs/Web3Eth) package can be used to fetch data from the Ethereum network: @@ -85,18 +85,18 @@ await web3.eth.getGasPrice(); // ↳ 23879160756n ``` -## Setting up a wallet +## Setting Up a Wallet To send transactions to the Ethereum network (e.g. [transferring ETH](/guides/getting_started/quickstart#transfer-eth) or [interacting with smart contracts](/guides/getting_started/quickstart#interact-with-smart-contracts)), it's necessary to use an [account](https://ethereum.org/en/developers/docs/accounts/) with funds to cover [gas fees](https://ethereum.org/en/developers/docs/gas/). The [`Wallet`](/api/web3-eth-accounts/class/Wallet) object is designed to manage a set of accounts that can be used to send transactions with [`web3.eth.sendTransaction`](/api/web3/class/Web3Eth#sendTransaction) or [`web3.eth.contract.methods.contractfunction().send()`](/api/web3-eth-contract/class/Contract). -### Create a random account +### Create a Random Account Using the `Wallet` to create a random account is a good way to accelerate the development process, but it's not suitable for mainnet or production uses, since random accounts will not have funds to cover gas fees. Use the [`Wallet.create`](/api/web3-eth-accounts/class/Wallet#create) method to create a random account. ```ts -//create random wallet with 1 account +// create random wallet with 1 account web3.eth.accounts.wallet.create(1) /* ↳ Wallet(1) @@ -119,7 +119,7 @@ Wallet(1) */ ``` -### Add an account from a private key +### Add an Account from a Private Key Use the [`Wallet.add`](/api/web3-eth-accounts/class/Wallet#add) method to use a private key to add an existing account to a wallet. @@ -128,7 +128,7 @@ Private keys are sensitive data and should be treated as such. Make sure that pr ::: ```ts -//the private key must start with the '0x' prefix +// the private key must start with the "0x" prefix const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); console.log(account[0].address); @@ -143,39 +143,39 @@ console.log(account[0].privateKey); This is an example of using a private key to add an account to a wallet, and then using that account to transfer ETH: ```ts -//add an account to a wallet +// add an account to a wallet const account = web3.eth.accounts.wallet.add('0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec'); -//create transaction object to send 1 eth to '0xa32...c94' address from the account[0] +// create transaction object to send 1 eth to '0xa32...c94' address from the account[0] const tx = { from: account[0].address, to: '0xa3286628134bad128faeef82f44e99aa64085c94', value: web3.utils.toWei('1', 'ether') }; -//the `from` address must match the one previously added with wallet.add +// the "from" address must match the one previously added with wallet.add -//send the transaction +// send the transaction const txReceipt = await web3.eth.sendTransaction(tx); console.log('Tx hash:', txReceipt.transactionHash) // ↳ Tx hash: 0x03c844b069646e08af1b6f31519a36e3e08452b198ef9f6ce0f0ccafd5e3ae0e ``` -## Interact with smart contracts +## Interact with Smart Contracts [Smart contracts](https://ethereum.org/en/developers/docs/smart-contracts/) are programs that run on the Ethereum network. Keep reading to learn how to use Web3.js to interact with smart contracts. -### Instantiate a contract +### Instantiate a Smart Contract The first step to interacting with a smart contract is to instantiate it, which requires the [ABI](https://docs.soliditylang.org/en/develop/abi-spec.html) and address of the smart contract. The following examples demonstrates instantiating the [Uniswap](https://uniswap.org/) token smart contract: ```ts -//Uniswap token smart contract address (mainnet) +// Uniswap token smart contract address (Mainnet) const address = '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984' -//you can find the complete ABI in etherscan.io -//https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code +// you can find the complete ABI on etherscan.io +// https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code const ABI = [ { @@ -190,60 +190,63 @@ const ABI = }, ]; -//instantiate the smart contract +// instantiate the smart contract const uniswapToken = new web3.eth.Contract(abi, address); ``` -### Read methods +### Read Methods Since reading data from a smart contract does not consume any gas, it's not necessary to use an account to do so. Here are some examples of reading data from the Uniswap token smart contract: ```ts -//make the call to the contract +// make the call to the contract const symbol = await uniswapToken.methods.symbol().call(); console.log('Uniswap symbol:',symbol); // ↳ Uniswap symbol: UNI -//make the call to the contract +// make the call to the contract const totalSupply = await uniswapToken.methods.totalSupply().call(); console.log('Uniswap Total supply:', totalSupply); // ↳ Uniswap Total Supply: 1000000000000000000000000000n ``` -### Write methods +### Write Methods Writing data to a smart contract consumes gas and requires the use of an account with funds. The following example demonstrates such an interaction: ```ts -//address to send the token +// address to send the token const to = '0xcf185f2F3Fe19D82bFdcee59E3330FD7ba5f27ce'; -//value to transfer (1 with 18 decimals) +// value to transfer (1 with 18 decimals) const value = web3.utils.toWei('1','ether'); -//send the transaction => return the Tx receipt +// send the transaction => return the Tx receipt const txReceipt = await uniswapToken.methods.transfer(to,value).send({from: account[0].address}); console.log('Tx hash:',txReceipt.transactionHash); // ↳ Tx hash: 0x14273c2b5781cc8f1687906c68bfc93482c603026d01b4fd37a04adb6217ad43 ``` -### Query past events +### Query Past Events Smart contracts emit [events](https://ethereum.org/en/developers/docs/smart-contracts/anatomy/#events-and-logs) to communicate important interactions. This example demonstrates how to query the Uniswap token smart contract for all `Transfer` events that occurred after a certain block number: ```ts -//get past `Transfer` events from block 18850576 +// get past `Transfer` events from block 18850576 const eventTransfer = await uniswapToken.getPastEvents('Transfer', { fromBlock: 18850576 }); console.log(eventTransfer); // ↳ [{...},{...}, ...] array with all the events emitted -//you can only query logs from the previous 100_000 blocks ``` -### Subscribing to events +:::note +You can only query logs from the most recent 100,000 blocks. +::: + +### Subscribing to Events Web3.js allows user to subscribe to events for real-time notification of important contract interactions. Here is an example of creating a subscription to the Uniswap token's `Transfer` event: @@ -254,16 +257,16 @@ HTTP providers do not support real-time event subscriptions. Use one of the othe ```ts import { Web3 } from 'web3'; -//WebSocket provider +// WebSocket provider const web3 = new Web3('wss://ethereum.publicnode.com'); -//instantiate contract +// instantiate contract const uniswapToken = new web3.eth.Contract(abi, address) -//create the subcription to all the 'Transfer' events +// create the subscription to all the 'Transfer' events const subscription = uniswapToken.events.Transfer(); -//listen to the events +// listen to the events subscription.on('data',console.log); // ↳ [{...},{...}, ...] live events will be printed in the console ``` diff --git a/docs/docs/guides/web3_providers_guide/index.md b/docs/docs/guides/web3_providers_guide/index.md index 1c1a0c334cb..726ccd8c229 100644 --- a/docs/docs/guides/web3_providers_guide/index.md +++ b/docs/docs/guides/web3_providers_guide/index.md @@ -3,7 +3,7 @@ sidebar_position: 1 sidebar_label: 'Mastering Providers' --- -# Web3js providers overview +# Web3.js Providers Overview Providers are services that are responsible for enabling Web3.js connectivity with the Ethereum network. Using a provider to connect your application to an Ethereum node is necessary for querying data, sending transactions, and interacting with smart contracts. This guide will explore the different types of Web3.js providers, how to set them up, and how to use them in an application. @@ -14,7 +14,7 @@ import { Web3 } from 'web3'; const web3 = new Web3(/* PROVIDER*/); -//calling any method that interact with the network would use the previous passed provider. +// calling any method that interacts with the network will use the supplied provider await web3.eth.getBlockNumber(); ``` @@ -40,8 +40,8 @@ HTTP is a request-response protocol and does not support persistent connection, ``` ts title='Initialize an HTTP Provider' import { Web3, HttpProvider } from 'web3'; -//supply an HTTP provider as a URL string -//highlight-next-line +// supply an HTTP provider as a URL string +// highlight-next-line const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_ID'); await web3.eth.getBlockNumber() @@ -49,8 +49,8 @@ await web3.eth.getBlockNumber() // OR -//supply an HTTP provider by constructing a new HttpProvider -//highlight-next-line +// supply an HTTP provider by constructing a new HttpProvider +// highlight-next-line const web3_2 = new Web3(new HttpProvider('https://mainnet.infura.io/v3/YOUR_INFURA_ID')); await web3.eth.getBlockNumber() @@ -87,15 +87,15 @@ const httpOptions = { const web3 = new Web3(new HttpProvider('https://eth.llamarpc.com', httpOptions)); ``` -### WebSocket provider +### WebSocket Provider WebSockets support a persistent connection between a client and a server, which means they are suitable for use cases that require real-time [event subscriptions](/guides/events_subscriptions/). ``` ts title='Initialize WS Provider' import { Web3, WebSocketProvider } from 'web3'; -//supply a WebSocket provider as a URL string -//highlight-next-line +// supply a WebSocket provider as a URL string +// highlight-next-line const web3 = new Web3('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID'); await web3.eth.getBlockNumber(); @@ -103,8 +103,8 @@ await web3.eth.getBlockNumber(); // OR -//supply a WebSocket provider by constructing a new WebSocketProvider -//highlight-next-line +// supply a WebSocket provider by constructing a new WebSocketProvider +// highlight-next-line const web3_2 = new Web3(new WebSocketProvider('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_ID')); await web3.eth.getBlockNumber(); @@ -116,12 +116,12 @@ await web3.eth.getBlockNumber(); The [`WebSocketProvider` constructor](/api/web3-providers-ws/class/WebSocketProvider#constructor) accepts two optional parameters that can be used to configure the behavior of the `WebSocketProvider`: the first parameter must be of type [`ClientRequestArgs`](https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules__types_node_http_d_._http_.clientrequestargs.html) or of [`ClientOptions`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e5ee5eae6a592198e469ad9f412bab8d223fcbb6/types/ws/index.d.ts#L243) and the second parameter must be of type [`ReconnectOptions`](/api/web3/namespace/utils#ReconnectOptions). ```ts title='Configuring a WebSocket Provider' -//include both optional parameters +// include both optional parameters const provider = new WebSocketProvider( `ws://localhost:8545`, { headers: { - //for node services that require an API key in a header + // for node services that require an API key in a header 'x-api-key': '', }, }, @@ -132,7 +132,7 @@ const provider = new WebSocketProvider( } ); -//OR include only ReconnectOptions +// OR include only ReconnectOptions const provider = new WebSocketProvider( `ws://localhost:8545`, {}, @@ -150,10 +150,10 @@ IPC (inter-process communication) providers offer high-performance local communi ``` ts title='Initialize IPC Provider' import { Web3 } from 'web3'; -//highlight-next-line +// highlight-next-line import { IpcProvider } from 'web3-providers-ipc'; -//highlight-next-line +// highlight-next-line const web3 = new Web3(new IpcProvider('/users/myuser/.ethereum/geth.ipc')); await web3.eth.getBlockNumber(); @@ -167,7 +167,7 @@ The [`IpcProvider` constructor](/api/web3-providers-ipc/class/IpcProvider#constr ```ts title='Configuring an IPC Provider' -//include both optional parameters +// include both optional parameters const provider = new IpcProvider( '/Users/myuser/Library/Ethereum/geth.ipc', { @@ -180,7 +180,7 @@ const provider = new IpcProvider( } ); -//OR include only ReconnectOptions +// OR include only ReconnectOptions const provider = new IpcProvider( '/Users/myuser/Library/Ethereum/geth.ipc', {}, @@ -208,22 +208,23 @@ Local providers can usually be accessed via IPC, HTTP, or WebSocket. The followi import { Web3 } from 'web3'; import { IpcProvider } from 'web3-providers-ipc'; -//highlight-next-line -//IPC provider -const web3 = new Web3(new IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc'));//mac os path -// on windows the path is: '\\\\.\\pipe\\geth.ipc' -// on linux the path is: '/users/myuser/.ethereum/geth.ipc' +// highlight-next-line +// IPC provider +const web3 = new Web3(new IpcProvider('/Users/myuser/Library/Ethereum/geth.ipc')); +// the path above is for macOS +// on Windows the path is: '\\\\.\\pipe\\geth.ipc' +// on Linux the path is: '/users/myuser/.ethereum/geth.ipc' -//highlight-next-line -//HTTP provider +// highlight-next-line +// HTTP provider web3.setProvider('http://localhost:8545'); -// or +// OR web3.setProvider(new Web3.providers.HttpProvider('http://localhost:8545')); -//highlight-next-line -//WebSocket provider +// highlight-next-line +// WebSocket provider web3.setProvider('ws://localhost:8546'); -// or +// OR web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546')); ``` @@ -232,8 +233,6 @@ web3.setProvider(new Web3.providers.WebsocketProvider('ws://localhost:8546')); Services like [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/), and [QuickNode](https://www.quicknode.com/) offer Ethereum node services that can be accessed via HTTP or Websocket. ```ts title='Alchemy, Infura, etc' -// like Alchemy (https://www.alchemyapi.io/supernode) -// or infura (https://mainnet.infura.io/v3/your_infura_key) import { Web3 } from 'web3'; const web3 = new Web3('https://eth-mainnet.alchemyapi.io/v2/your-api-key'); ``` @@ -250,24 +249,24 @@ The following example should be run in a browser with the MetaMask extension ins - - - -``` - -7. Create a new file called `server.js` (inside `web3-browser-injected-providers`). -8. Copy and paste the following code into `server.js`, and save it after: - -```js -const express = require('express'); -const app = express(); -const path = require('path'); - -app.use(express.static(path.join(__dirname, '.'))); - -app.listen(8097, () => { - console.log('Server started on port 8097'); -}); -``` - -9. Start the Node.js server by executing the following command. This will execute the content of `server.js` which will run the server on port 8097: - -```bash -node server.js -``` - -10. Open your web browser and navigate to `http://localhost:8097/`. MetaMask should ask for your approval to connect to your website. Follow the steps and give your consent. -11. If everything is set up properly, you should be able to connect to the Ethereum network with MetaMask and see the logged account address. - -Note that in the above steps you had created a local web server using Node.js and Express, serving your HTML file from the root directory of your project. You needs this local server because many browser does not allow extensions to inject objects for static files located on your machine. However, you can customize the port number and the root directory if needed. - -Now you can start building your Ethereum application with web3.js and MetaMask! diff --git a/docs/docs/guides/web3_providers_guide/ipc.md b/docs/docs/guides/web3_providers_guide/ipc.md deleted file mode 100644 index 1b31eb44f2b..00000000000 --- a/docs/docs/guides/web3_providers_guide/ipc.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -sidebar_position: 6 -sidebar_label: 'Tutorial: IPC Provider' ---- - -# Tutorial: IPC Provider - -The IPC Provider offers high-performance local communication, providing a swift alternative to the straightforward HTTP Provider. Tailored for efficiency, it excels in local environments, enhancing the speed of your web application's connection to the Ethereum network for decentralized applications. - -## Prerequisites - -Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: - -1. **Node.js** - - Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). - -2. **npm** - - npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). - - Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). - -3. **Geth** (Optional, used only at the IPC provider example) - - Geth (go-ethereum) is an Ethereum execution client meaning it handles transactions, deployment and execution of smart contracts and contains an embedded computer known as the Ethereum Virtual Machine. You can install it by following the instructions here: [https://geth.ethereum.org/docs/getting-started/installing-geth](https://geth.ethereum.org/docs/getting-started/installing-geth) - -## IPC Provider (for Node.js) - -The IPC Provider allows you to connect to an Ethereum node using Inter-Process Communication (IPC) in a Node.js environment. This provider is useful when you have a local Ethereum node running on your machine and want to interact with it using Node.js. - -In the following steps you will run `geth` in development mode and you will run a piece of code that reads the Ethereum accounts and sends a transaction: - -To connect to the Ethereum network using the IPC provider, follow these steps: - -1. Start a `geth` node in development mode by opening a terminal window and navigating to the `geth` executable file. Then, run the following command to create a development chain: - -```bash -geth --dev --ipcpath -``` - -Make sure to replace `` with the desired IPC path. For example: - -```bash -geth --dev --ipcpath /Users/username/Library/Ethereum/geth.ipc -``` - -This will start a `geth` node in development mode with IPC enabled and an IPC path specified. If the command is successful, the `geth` node will be running, and you should see output similar to the following: - -```bash -INFO [12-10|15:10:37.121] IPC endpoint opened url= -INFO [12-10|15:10:37.122] HTTP endpoint opened url=http://localhost:8545 -INFO [12-10|15:10:37.122] WebSocket endpoint opened url=ws://localhost:8546 -INFO [12-10|15:10:37.127] Mapped network port proto=udp extport=0 intport=30303 interface=UPnP(UDP) -``` - -2. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. -3. Create a new folder and navigate to it: - -```bash -mkdir web3-providers-tutorial -cd web3-providers-tutorial -``` - -4. Install web3.js using npm: - -```bash -npm i web3 -``` - -5. Create a new JavaScript file called `web3-ipc-provider.js` in your code editor. - -6. Copy and paste the following code into your `web3-ipc-provider.js` file and save it: - -```typescript title='IPC Provider' -import { Web3 } from 'web3'; -import { IpcProvider } from 'web3-providers-ipc'; - -// Connect to the Ethereum network using IPC provider -const ipcPath = ''; // Replace with your actual IPC path -const ipcProvider = new IpcProvider(ipcPath); - -const web3 = new Web3(ipcProvider); - -async function main() { - try { - console.log('Does the provider support subscriptions?:', ipcProvider.supportsSubscriptions()); - - // Get the list of accounts in the connected node which is in this case: geth in dev mode. - const accounts = await web3.eth.getAccounts(); - console.log('Accounts:', accounts); - - // Send a transaction to the network - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[0], // sending a self-transaction - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - } catch (error) { - console.error('An error occurred:', error); - } -} - -main(); -``` - -7. replace `` with the `ipcPath` that you had specified, when starting the `geth` node, in the first step. - -8. Type `node web3-ipc-provider.js` in the command prompt or terminal window and press Enter. This will run your JavaScript file. - -If everything is set up properly, you should see the list of accounts and transaction receipt printed in the console, similar to the following: - -```bash -Do the provider supports subscription?: true -Accounts: [ '0x82333ED0FAA7a883297C4d8e0FDE1E1CFABAeB7D' ] -Transaction Receipt: { - blockHash: '0xd1220a9b6f86083e420da025179593f5aad3732165a687019a89528a4ab2bcd8', - blockNumber: 1n, - cumulativeGasUsed: 21000n, - effectiveGasPrice: 1000000001n, - from: '0x82333ed0faa7a883297c4d8e0fde1e1cfabaeb7d', - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - status: 1n, - to: '0x82333ed0faa7a883297c4d8e0fde1e1cfabaeb7d', - transactionHash: '0x76c05df78dc5dbfade0d11322b3cadc894c17efe36851856aca29488b47c3fbd', - transactionIndex: 0n, - type: 0n -} -``` - -Keep in mind that using IPC Provider with `geth` in development mode in a production environment is not recommended as it can pose a security risk. diff --git a/docs/docs/guides/web3_providers_guide/truffle.md b/docs/docs/guides/web3_providers_guide/truffle.md deleted file mode 100644 index ba98c3a3335..00000000000 --- a/docs/docs/guides/web3_providers_guide/truffle.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -sidebar_position: 8 -sidebar_label: 'Tutorial: Third Party Provider' ---- - -# Truffle - -The Truffle HDWallet Provider will be used as an example of a third party provider that is EIP 1193 compatible. - -## Prerequisites - -Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: - -1. **Ganache** - - Ganache is a personal blockchain for Ethereum development that allows you to test how your smart contracts function in real-world scenarios. You can download it from [http://truffleframework.com/ganache](http://truffleframework.com/ganache). - -2. **Node.js** - - Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). - -3. **npm** - - npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). - - Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). - -## Third-party Providers (Compliant with EIP 1193) - -web3.js accepts any provider that is in compliance with [EIP-1193](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md). It has tests written to ensure compatibility with @truffle/hdwallet-provider, Ganache provider, Hardhat provider, and Incubed (IN3) as a provider. The following section, [Browser Injected Ethereum Provider](#browser-injected-ethereum-provider), in this tutorial explains how to use a special case of these third-party providers. - -Here is a step-by-step example and a code snippet to connect your web application to the Ethereum network using `@truffle/hdwallet-provider` as an example of an external provider compliant with EIP 1193. - -1. Open a command prompt or terminal window in a new folder. -2. Type `npm init -y` and press Enter. This will create a `package.json` file in the current directory. -3. Install web3.js and HTTP provider using npm: - -```bash -npm i web3 @truffle/hdwallet-provider bip39 -``` - -4. Create a new JavaScript file, called `index.js`, in your code editor. -5. Copy and paste the following code into your JavaScript file, and then save the file: - -```typescript title='EIP1193 Provider (Truffle)' -import { Web3 } from 'web3'; -import HDWalletProvider from '@truffle/hdwallet-provider'; -import bip39 from 'bip39'; - -const mnemonic: string = bip39.generateMnemonic(); // generates seed phrase -console.log('seed phrase:', mnemonic); - -// Connect to the Ethereum network using an HTTP provider and WalletProvider -const provider: HDWalletProvider = new HDWalletProvider(mnemonic, 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'); -const web3: Web3 = new Web3(provider); - -// Get the current block number from the network -web3.eth - .getBlockNumber() - .then(function (blockNumber: number) { - console.log('Current block number:', blockNumber); - }) - .catch(function (error: any) { - console.log('Error:', error); - }); -``` - -6. Replace `'YOUR_INFURA_PROJECT_ID'` with your own Infura project ID. You can obtain an Infura project ID by signing up for a free account at https://infura.io/register. Alternatively, you can use any other URL that is compatible with HDWalletProvider, such as a local Ganache accessible at `'http://localhost:7545'`. - -7. In the command prompt, run `node index.js` and press Enter. This will execute your JavaScript file and connect to the Ethereum network using HDWalletProvider with Infura. - -If everything is set up properly, you should see the current block number printed in the console similar to the following. - -```bash -seed phrase: remain climb clock valid budget cable tunnel force split level measure repair -Current block number: 17317844n -``` - -:::danger -Your seed phrase gives complete access to your Ethereum account and it should **never** be shared with anyone you don't want to give full access to your account. The seed phrase is `console.log`ed in the code example to show you what it looks like, but you should **never** do this with a seed phrase to an account you plan on using to send real money. -::: - -The sample above connected you to the Ethereum network using truffle HD Wallet-enabled Web3 provider. You can modify it to interact with the network, perform transactions, and read/write data from the Ethereum network. - diff --git a/docs/docs/guides/web3_providers_guide/websocket.md b/docs/docs/guides/web3_providers_guide/websocket.md deleted file mode 100644 index 96288f4e031..00000000000 --- a/docs/docs/guides/web3_providers_guide/websocket.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: 'Tutorial: WebSocket Provider' ---- - -# Tutorial: WebSocket Provider - -The WebSocket Provider provides real-time communication and enhanced performance, offering a dynamic alternative to the simplicity of the HTTP Provider. In comparison to the widely used HTTP Provider, the WebSocket Provider enables your web application to establish a continuous, bidirectional connection, allowing for live updates and faster interactions with the Ethereum network. Incorporate the WebSocket Provider to empower your decentralized applications with real-time capabilities. - -## Prerequisites - -Before we get started, make sure you have a basic understanding of JavaScript and Ethereum. Additionally, we need to set up our environment by installing the following: - -1. **Ganache** - - Ganache is a personal blockchain for Ethereum development that allows you to test how your smart contracts function in real-world scenarios. You can download it from [http://truffleframework.com/ganache](http://truffleframework.com/ganache). - -2. **Node.js** - - Node.js is a JavaScript runtime environment that enables you to run JavaScript on the server-side. You can download it from [https://nodejs.org/en/download/](https://nodejs.org/en/download/). - -3. **npm** - - npm (Node Package Manager) is used to publish and install packages to and from the public npm registry or a private npm registry. You can install it by following the instructions here: [https://docs.npmjs.com/downloading-and-installing-node-js-and-npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). - - Alternatively, you can use **yarn** instead of **npm** by following the instructions here: [https://classic.yarnpkg.com/lang/en/docs/getting-started/](https://classic.yarnpkg.com/lang/en/docs/getting-started/). - -## WebSocket Provider - -WebSocket Provider allows us to communicate with the Ethereum node via WebSocket protocol, which is useful when we want continuous updates on our subscribed items. This provider is ideal for real-time applications that require constant updates from the Ethereum network. - -Follow these steps to connect to the Ethereum network using WebSocket provider: - -:::tip -The first 3 steps are the same as in the previous section. So, you may skip them if you already executed the previous section. -::: - -1. Open a command prompt or terminal window and navigate to where you would like to create the folder for this example. -2. Create a new folder and navigate to it: - -```bash -mkdir web3-providers-tutorial -cd web3-providers-tutorial -``` - -3. Install web3.js using npm: - -```bash -npm i web3 -``` - -4. Create a new JavaScript file called `web3-websocket-provider.js` in your code editor. - -5. Copy and paste the following code into your `web3-websocket-provider.js` file and save it: - -```typescript title='WebSocket Provider' -import { Web3 } from 'web3'; - -// Connect to the Ethereum network using WebSocket provider -const ganacheUrl = 'ws://localhost:8545'; -const wsProvider = new Web3.providers.WebsocketProvider(ganacheUrl); -const web3 = new Web3(wsProvider); - -async function main() { - try { - console.log('Does the provider support subscriptions?:', wsProvider.supportsSubscriptions()); - - // Subscribe to new block headers - const subscription = await web3.eth.subscribe('newBlockHeaders'); - - subscription.on('data', async (blockhead) => { - console.log('New block header: ', blockhead); - - // You do not need the next line if you like to keep being notified for every new block - await subscription.unsubscribe(); - console.log('Unsubscribed from new block headers.'); - }); - subscription.on('error', (error) => console.log('Error when subscribing to New block header: ', error)); - - // Get the list of accounts in the connected node which is in this case: Ganache. - const accounts = await web3.eth.getAccounts(); - // Send a transaction to the network - const transactionReceipt = await web3.eth.sendTransaction({ - from: accounts[0], - to: accounts[1], - value: web3.utils.toWei('0.001', 'ether'), - }); - console.log('Transaction Receipt:', transactionReceipt); - } catch (error) { - console.error(error); - } -} - -main(); -``` - -6. Ensure that Ganache is running as mentioned in the [Prerequisites](#prerequisites) section. - -7. Type `node web3-websocket-provider.js` in the command prompt or terminal window and press Enter. This will run your JavaScript file. - -If everything is set up properly, you should see the new block headers, transaction hash, and pending transaction printed in the console. The unique feature of WebSocket provider highlighted in this example is that it can subscribe to new block headers and pending transactions to get them in real-time. And by running the sample, you will get something similar to this in your console: - -```bash -Do the provider supports subscription?: true -New block header: { - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - miner: '0x0000000000000000000000000000000000000000', - difficulty: '0', - totalDifficulty: '0', - extraData: '0x', - gasLimit: 6721975, - gasUsed: 21000, - hash: '0xd315cecf3336640bcd1301930805370b7fe7528c894b931dcf8a3b1c833b68c8', - mixHash: '0x1304070fde1c7bee383f3a59da8bb94d515cbd033b2638046520fb6fb596d827', - nonce: '0x0000000000000000', - number: 40, - parentHash: '0xeb7ce3260911db2596ac843df11dbcbef302e813e1922db413f6f0b2a54d584d', - receiptsRoot: '0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa', - stateRoot: '0x95e416eec0932e725ec253779a4e28b3d014d05e41e63c3369f5da42d26d1240', - timestamp: 1684165088, - transactionsRoot: '0x8f87380cc7acfb6d10633e10f72567136492cb8301f52a41742eaca9449bb378', - sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', - baseFeePerGas: 4959456, - size: undefined -} -Transaction Receipt: { - transactionHash: '0x0578672e97d072b4b91773c8bfc710e4f777616398b82b276323408e59d11362', - transactionIndex: 0n, - blockNumber: 1n, - blockHash: '0x5c05248fe0fb8f45a8c9b9600904a36c0e5c74dce01495cfc72278c185fe7838', - from: '0x6e599da0bff7a6598ac1224e4985430bf16458a4', - to: '0x6f1df96865d09d21e8f3f9a7fba3b17a11c7c53c', - cumulativeGasUsed: 21000n, - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - status: 1n, - effectiveGasPrice: 2000000000n, - type: 0n -} -Unsubscribed from new block headers. -``` From b234c1c01f67a414e13a084a7a9c172b5ea1769a Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 10 Jun 2024 07:12:59 -0700 Subject: [PATCH 20/25] fix(docs): mastering-accounts (#7089) * Updates to Mastering (Introduction to) Accounts & Wallets * Add a note about wallet context --- docs/docs/guides/wallet/image.jpeg | Bin 156303 -> 0 bytes docs/docs/guides/wallet/index.md | 372 +++++++++++++++++------------ 2 files changed, 224 insertions(+), 148 deletions(-) delete mode 100644 docs/docs/guides/wallet/image.jpeg diff --git a/docs/docs/guides/wallet/image.jpeg b/docs/docs/guides/wallet/image.jpeg deleted file mode 100644 index 455abbf9bcf00f698b143b3d1d8a16ecc8e4a622..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156303 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

bj@$5^GYX@3Oys#JDt%r5LwzkBpW*}UA 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 nEL3)l0!s6II9n diff --git a/docs/docs/guides/wallet/index.md b/docs/docs/guides/wallet/index.md index 9dd38e750b5..0e8858ad530 100644 --- a/docs/docs/guides/wallet/index.md +++ b/docs/docs/guides/wallet/index.md @@ -1,65 +1,118 @@ --- sidebar_position: 1 -sidebar_label: 'Mastering Wallets & Accounts' +sidebar_label: 'Introduction to Accounts & Wallets' --- -# Wallets and Accounts Overview +# Introduction to Accounts & Wallets +The concept of an [account](https://ethereum.org/en/developers/docs/accounts/) is central to Ethereum and it can be used to refer to two types of entities that are native to Ethereum: externally-owned accounts and contract accounts. This document relates _exclusively_ to **externally-owned accounts**. An externally-owned account is associated with a "[key pair](https://ethereum.org/en/developers/docs/accounts/#externally-owned-accounts-and-key-pairs)", which is a general concept that is related to [public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography). The key pair consists of a private key, which must always be kept secret, and a public key, which is used to derive a public identifier (address) for an account. Ethereum accounts have an [ETH](https://ethereum.org/en/developers/docs/intro-to-ethereum/#eth) balance, which can be [transferred](/guides/wallet/transactions) to other accounts or used to pay for interactions with [smart contracts](/guides/smart_contracts/smart_contracts_guide). Anyone with access to an account's private key has the ability to control that account's ETH balance, so it's important that an account's private key is always kept secret. In addition to the general guidelines for [protecting private keys](https://ethereum.org/en/security/#protect-private-keys/), private keys should never be included in client-side code that can be seen by end users and should never be committed to code repositories. -## Live code editor +In the context of this document, the term "wallet" refers to a collection of accounts and should not be confused with [wallet "applications"](https://ethereum.org/en/wallets/). - +## Accounts -## Introduction +The [`web3-eth-accounts`](/api/web3-eth-accounts) package contains functions to generate Ethereum accounts, sign transactions and data, and more. In Web3.js, the [`Web3Account`](/api/web3-eth-accounts/interface/Web3Account) interface is used to represent an externally-owned account. The following snippet demonstrates using Web3.js to generate a new random account and then using that account to sign a message: -A Web3.js `Wallet` is your main entry point if you want to use a private key directly to do any blockchain operations (transactions), also called `Signer` in other libraries. - -Unlike other libraries where a wallet holds just one account, a Web3.js `Wallet` can handle **multiple accounts**. They each have their private key and address. So, whether those keys are in your computer's memory or protected by MetaMask, the Wallet makes Ethereum tasks secure and simple. - -The `web3-eth-accounts` package contains functions to generate Ethereum accounts and sign transactions and data. - -In Ethereum, a private key is a critical part of the cryptographic key pair used to secure and control ownership of Ethereum addresses. Each Ethereum address has a matching set of public and private keys in a public-key cryptography system. This key pair enables you to own an Ethereum address, manage funds, and initiate transactions. - -Learn more about wallets [here](https://ethereum.org/en/wallets/) - -You can sign and send transactions in different ways. +```js +// generate a new random account +const account = web3.eth.accounts.create(); -- [Local wallet](./local_wallet) **(Highly recommended)** -- [Node Wallet](./node_wallet) **(Deprecated)** +console.log(account); +/* ↳ +{ + address: '0x9E82491d1978217d631a3b467BF912933F54788f', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] +} +*/ -For each of them you can use [Web3PromiEvent](./promi_event) to catch extra transaction's events. +// use the account to sign a message +const signature = account.sign("Hello, Web3.js!"); +/* ↳ +{ + message: 'Hello, Web3.js!', + messageHash: '0xc0f5f7ee704f1473acbb7959f5f925d787a9aa76dccc1b4914cbe77c09fd68d5', + v: '0x1b', + r: '0x129822b685d4404924a595af66c9cdd6367a57c66ac66e2e10fd9915d4772fbd', + s: '0x62db48d6f5e47fe87c64a0991d6d94d23b6024d5d8335348f6686b8c46edb1e9', + signature: '0x129822b685d4404924a595af66c9cdd6367a57c66ac66e2e10fd9915d4772fbd62db48d6f5e47fe87c64a0991d6d94d23b6024d5d8335348f6686b8c46edb1e91b' +} +*/ +``` -## Wallets vs Accounts +Note that many of these values will change each time the code is executed, since a new account is created each time. -An **account** in web3.js is an `object`, it refers to an individual Ethereum address with its associated public and private keys. While a wallet is a higher-level construct for managing multiple accounts, an individual Ethereum address is considered an account. +In addition to generating new random accounts, the Account package can also be used to load an existing account from its private key, as in the following snippet: -```ts title='Create a new account' -const account = web3.eth.accounts.create(); +```js +// load an existing account from its private key +const account = web3.eth.accounts.privateKeyToAccount(""); -console.log(account) -/* ↳ +console.log(account); +/* ↳ { address: '0x9E82491d1978217d631a3b467BF912933F54788f', - privateKey: '0x4651f9c219fc6401fe0b3f82129467c717012287ccb61950d2a8ede0687857ba', + privateKey: '', signTransaction: [Function: signTransaction], sign: [Function: sign], encrypt: [Function: encrypt] } */ + +// use the account to sign a message +const signature = account.sign("Hello, Web3.js!"); +/* ↳ +{ + message: 'Hello, Web3.js!', + messageHash: '0xc0f5f7ee704f1473acbb7959f5f925d787a9aa76dccc1b4914cbe77c09fd68d5', + v: '0x1b', + r: '0x129822b685d4404924a595af66c9cdd6367a57c66ac66e2e10fd9915d4772fbd', + s: '0x62db48d6f5e47fe87c64a0991d6d94d23b6024d5d8335348f6686b8c46edb1e9', + signature: '0x129822b685d4404924a595af66c9cdd6367a57c66ac66e2e10fd9915d4772fbd62db48d6f5e47fe87c64a0991d6d94d23b6024d5d8335348f6686b8c46edb1e91b' +} +*/ ``` -A **wallet** in web3.js is an `array` that holds multiple Ethereum accounts. It provides a convenient way to manage and interact with a collection of accounts. Think of it as a digital wallet that you use to store and organize your various Ethereum addresses. +### Account Methods -```ts title='Create a new wallet' -//create a wallet with `1` random account -const wallet = web3.eth.accounts.wallet.create(1); +The following is a list of [`Accounts`](/libdocs/Accounts) methods in the `web3.eth.accounts` package with descriptions and example usage: + +- [create](/libdocs/Accounts#create) +- [decrypt](/libdocs/Accounts#decrypt) +- [encrypt](/libdocs/Accounts#encrypt) +- [hashMessage](/libdocs/Accounts#hashMessage) +- [parseAndValidatePrivateKey](/libdocs/Accounts#libdocs/Accounts#parseandvalidateprivatekey) +- [privateKeyToAccount](/libdocs/Accounts#privatekeytoaccount) +- [privateKeyToAddress](/libdocs/Accounts#privatekeytoaddress) +- [privateKeyToPublicKey](/libdocs/Accounts#privatekeytopublickey) +- [recover](/libdocs/Accounts#recover) +- [recoverTransaction](/libdocs/Accounts#recovertransaction) +- [sign](/libdocs/Accounts#sign) +- [signTransaction](/libdocs/Accounts#signtransaction) + +## Wallets + +A Web3.js wallet is a collection of accounts and is represented with the [`Wallet`](/api/web3-eth-accounts/class/Wallet) class. When a wallet is used to track an account, that account is added to an internal context (i.e. [`Web3Context`](/api/web3-core/class/Web3Context/)), which makes it easier to use that account in the future - this is described in more detail in the [transactions tutorial](/guides/wallet/transactions). The following snippet demonstrates creating a wallet with 2 new random accounts and using the second account to sign a message: + +```js +// create a wallet with 2 new random accounts +const wallet = web3.eth.accounts.wallet.create(2); console.log(wallet) -/* ↳ -Wallet(1) [ +/* ↳ +Wallet(2) [ + { + address: '0xaaD0d33dc9800258c1265bdDA47b9266472144F7', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, { - address: '0xB2D5647C03F36cA54f7d783b6Fa5afED297330d4', - privateKey: '0x7b907534ec13b19c67c2a738fdaa69014298c71f2221d7e5dec280232e996610', + address: '0x359caa845324802C64B97544460F31fba4f9B9ba', + privateKey: '', signTransaction: [Function: signTransaction], sign: [Function: sign], encrypt: [Function: encrypt] @@ -69,133 +122,166 @@ Wallet(1) [ privateKeyToAccount: [Function: privateKeyToAccountWithContext], decrypt: [Function: decryptWithContext] }, - _addressMap: Map(1) { '0xb2d5647c03f36ca54f7d783b6fa5afed297330d4' => 0 }, + _addressMap: Map(2) { + '0xaad0d33dc9800258c1265bdda47b9266472144f7' => 0, + '0x359caa845324802c64b97544460f31fba4f9b9ba' => 1 + }, _defaultKeyName: 'web3js_wallet' ] */ -``` - -## Diagram - -![Diagram wallet and accounts](image.jpeg) - -To learn more about the `accounts` methods, please visit [web3.js accounts API](/libdocs/Accounts) - -To learn more about the `wallet` methods, please visit [web3.js wallet API](/libdocs/Wallet) - -## Sending transactions - -The shortest way to do this, is by creating a `Wallet` directly by adding a private key (the private key must start with '0x' and it must have funds to execute the transaction) - -```ts title='Sending a transaction adding a privateKey' -import { Web3 } from 'web3'; - -const web3 = new Web3('https://ethereum-sepolia.publicnode.com'); -//this will create an array `Wallet` with 1 account with this privateKey -//it will generate automatically a public key for it -//make sure you have funds in this accounts -//highlight-next-line -const wallet = web3.eth.accounts.wallet.add('0x152c39c430806985e4dc16fa1d7d87f90a7a1d0a6b3f17efe5158086815652e5'); - -const _to = '0xc7203efeb54846c149f2c79b715a8927f7334e74'; -const _value = '1'; //1 wei - -//the `from` address in the transaction must match the address stored in our `Wallet` array -//that's why we explicitly access it using `wallet[0].address` to ensure accuracy -const receipt = await web3.eth.sendTransaction({ - from: wallet[0].address, - to: _to, - value: _value, -}); -//if you have more than 1 account, you can change the address by accessing to another account -//e.g, `from: wallet[1].address` - -console.log('Tx receipt:', receipt); +// use the second account in the wallet to sign a message +const signature = wallet[1].sign("Hello, Web3.js!"); +// wallet accounts can also be accessed with the "at" and "get" methods +// wallet.at(1).sign("Hello, Web3.js!") +// wallet.get(1).sign("Hello, Web3.js!") +console.log(signature); /* ↳ -Tx receipt: { - blockHash: '0xa43b43b6e13ba47f2283b4afc15271ba07d1bba0430bd0c430f770ba7c98d054', - blockNumber: 4960689n, - cumulativeGasUsed: 7055436n, - effectiveGasPrice: 51964659212n, - from: '0xa3286628134bad128faeef82f44e99aa64085c94', - gasUsed: 21000n, - logs: [], - logsBloom: '0x00000...00000000', - status: 1n, - to: '0xc7203efeb54846c149f2c79b715a8927f7334e74', - transactionHash: '0xb88f3f300f1a168beb3a687abc2d14c389ac9709f18b768c90792c7faef0de7c', - transactionIndex: 41n, - type: 2n +{ + message: 'Hello, Web3.js!', + messageHash: '0xc0f5f7ee704f1473acbb7959f5f925d787a9aa76dccc1b4914cbe77c09fd68d5', + v: '0x1c', + r: '0xd90fc42ff83fdf0ec6778c1c27f3051439de7844eacf06195c761fece19ed77d', + s: '0x729693156c48d07df9f4970772049dbe24ebce979765f788974a13c318b2834a', + signature: '0xd90fc42ff83fdf0ec6778c1c27f3051439de7844eacf06195c761fece19ed77d729693156c48d07df9f4970772049dbe24ebce979765f788974a13c318b2834a1c' } */ ``` -## Interacting with contracts - -### Writing functions +Note that many of these values will change each time the code is executed, since new accounts are created each time. -To interact with functions that modify or update data in smart contracts(writing-functions), we need to create a `Wallet`. This `Wallet` must holds at least 1 account with the necessary funds to execute these operations on the blockchain. +In addition to generating new random accounts, a wallet can also be used to load an existing account from its private key, as in the following snippet: -```ts title='Interacting with writing-functions of a smart contract' -import { Web3 } from 'web3'; +```js +// create a wallet with a single existing account +const wallet = web3.eth.accounts.wallet.add(""); -const web3 = new Web3('https://ethereum-sepolia.publicnode.com'); - -//create a wallet -//highlight-next-line -const wallet = web3.eth.accounts.wallet.add('0x152c39c430806985e4dc16fa1d7d87f90a7a1d0a6b3f17efe5158086815652e5'); - -//this is how we can access to the first account of the wallet -console.log('Account 1:', wallet[0]); +console.log(wallet); /* ↳ -Account 1: { - address: '0x57CaabD59a5436F0F1b2B191b1d070e58E6449AE', - privateKey: '0x152c39c430806985e4dc16fa1d7d87f90a7a1d0a6b3f17efe5158086815652e5', - ... -} +Wallet(1) [ + { + address: '0xC978F87516152f542dc4D6f64C810B0c206b11A8', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(1) { '0xc978f87516152f542dc4d6f64c810b0c206b11a8' => 0 }, + _defaultKeyName: 'web3js_wallet' +] */ +``` -//instantiate the contract -const myContract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); +New accounts can be added to an existing wallet, as is demonstrated by the following code snippet: -//interact with the contract -//wallet[0].address == '0x57CaabD59a5436F0F1b2B191b1d070e58E6449AE' -//highlight-next-line -const txReceipt = await myContract.methods.doSomething().send({ from: wallet[0].address }); +```js +// create a wallet with a single random accounts +const wallet = web3.eth.accounts.wallet.create(1); -console.log('Transaction receipt:', txReceipt); +console.log(wallet); /* ↳ - Transaction receipt: {...} +Wallet(1) [ + { + address: '0x6680D50C2165e8F1841D9CdaA42C2F1b949a39f2', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(1) { '0x6680d50c2165e8f1841d9cdaa42c2f1b949a39f2' => 0 }, + _defaultKeyName: 'web3js_wallet' +] */ -``` - -### Reading functions (view) - -To interact with smart contracts `view public/external returns`, we don't need to instantiate a `Wallet`, we can do it just by instantiating the smart contract and the provider. -```ts title='Interacting with reading-functions of a smart contract' -import { Web3 } from 'web3'; +// add a new account to the wallet with the wallet's "create" method +wallet.create(1); -//instantiate the provider -const web3 = new Web3('https://ethereum-sepolia.publicnode.com'); - -//instantiate the contract -const myContract = new web3.eth.Contract(ABI, CONTRACT_ADDRESS); +console.log(wallet); +/* ↳ +Wallet(2) [ + { + address: '0x6680D50C2165e8F1841D9CdaA42C2F1b949a39f2', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + { + address: '0x5eD8a3ED6Bb1f32e4B479380cFAcf43C49a5440A', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(2) { + '0x6680d50c2165e8f1841d9cdaa42c2f1b949a39f2' => 0, + '0x5ed8a3ed6bb1f32e4b479380cfacf43c49a5440a' => 1 + }, + _defaultKeyName: 'web3js_wallet' +] +*/ -//call the `view function` in the contract -//highlight-next-line -const result = await myContract.methods.doSomething().call(); +// create a new account and add it to the wallet +const newAccount = web3.eth.accounts.create(); +wallet.add(newAccount); -console.log('Result:', result) +console.log(wallet); /* ↳ - Result: ... +Wallet(3) [ + { + address: '0x6680D50C2165e8F1841D9CdaA42C2F1b949a39f2', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + { + address: '0x5eD8a3ED6Bb1f32e4B479380cFAcf43C49a5440A', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + { + address: '0x3065Cf410Bd6A10c5FF3Df8f60b82fF5Ee5db18a', + privateKey: '', + signTransaction: [Function: signTransaction], + sign: [Function: sign], + encrypt: [Function: encrypt] + }, + _accountProvider: { + create: [Function: createWithContext], + privateKeyToAccount: [Function: privateKeyToAccountWithContext], + decrypt: [Function: decryptWithContext] + }, + _addressMap: Map(3) { + '0x6680d50c2165e8f1841d9cdaa42c2f1b949a39f2' => 0, + '0x5ed8a3ed6bb1f32e4b479380cfacf43c49a5440a' => 1, + '0x3065cf410bd6a10c5ff3df8f60b82ff5ee5db18a' => 2 + }, + _defaultKeyName: 'web3js_wallet' +] */ ``` -## Wallet methods +### Wallet Methods -The following is a list of `Wallet` [methods](/libdocs/Wallet) in the `web3.eth.accounts.wallet` package with description and example usage: +The following is a list of [`Wallet`](/libdocs/Wallet) methods in the `web3.eth.accounts.wallet` package with description and example usage: - [add](/libdocs/Wallet#add) - [clear](/libdocs/Wallet#clear) @@ -208,20 +294,10 @@ The following is a list of `Wallet` [methods](/libdocs/Wallet) in the `web3.eth. - [save](/libdocs/Wallet#save) - [getStorage](/libdocs/Wallet#getStorage) -## Account methods - -The following is a list of `Accounts` [methods](/libdocs/Wallet) in the `web3.eth.accounts` package with description and example usage: +## Next Steps -- [create](/libdocs/Accounts#create) -- [decrypt](/libdocs/Accounts#decrypt) -- [encrypt](/libdocs/Accounts#encrypt) -- [hashMessage](/libdocs/Accounts#hashMessage) -- [parseAndValidatePrivateKey](/libdocs/Accounts#libdocs/Accounts#parseandvalidateprivatekey) -- [privateKeyToAccount](/libdocs/Accounts#privatekeytoaccount) -- [privateKeyToAddress](/libdocs/Accounts#privatekeytoaddress) -- [privateKeyToPublicKey](/libdocs/Accounts#privatekeytopublickey) -- [recover](/libdocs/Accounts#recover) -- [recoverTransaction](/libdocs/Accounts#recovertransaction) -- [sign](/libdocs/Accounts#sign) -- [signTransaction](/libdocs/Accounts#signtransaction) +This document is just an introduction to Web3.js accounts and wallets. Here are some suggestions for what to review next: +- Learn how to [transfer ETH](/guides/wallet/transactions) from one account to another. +- Build a front-end application that uses [injected accounts](/guides/wallet/metamask) from the MetaMask wallet. +- Use an account to [deploy and interact with a smart contract](/guides/smart_contracts/smart_contracts_guide). From 95476430782a30e6a6da80a452b5b2d670d98ce8 Mon Sep 17 00:00:00 2001 From: Junaid <86780488+jdevcs@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:35:32 +0200 Subject: [PATCH 21/25] transaction middleware (#7088) * add web3 packages references in context * call TXM in sendTx * Transaction Middleware * call txm * name fix * name fix 2 * txm example * txm plugin * unit tests * dependency * lint fix * test data * lint fix * fixed lint and unit test * unit tests in eth * changelog udpates --- packages/web3-core/CHANGELOG.md | 6 +- packages/web3-core/src/web3_context.ts | 3 + packages/web3-eth/CHANGELOG.md | 8 +- packages/web3-eth/src/rpc_method_wrappers.ts | 10 +- packages/web3-eth/src/types.ts | 17 +++ packages/web3-eth/src/web3_eth.ts | 15 ++- .../test/fixtures/transactions_data.ts | 117 ++++++++++++++++++ .../send_transaction_middleware.test.ts | 98 +++++++++++++++ .../web3_eth_methods_with_parameters.test.ts | 16 ++- packages/web3/CHANGELOG.md | 8 +- tools/web3-plugin-example/CHANGELOG.md | 6 +- tools/web3-plugin-example/package.json | 3 +- .../src/custom_rpc_methods.ts | 2 +- ...eware.ts => request_manager_middleware.ts} | 0 .../src/transaction_middleware.ts | 38 ++++++ .../src/transaction_middleware_plugin.ts | 44 +++++++ .../test/unit/fixtures/transactions_data.ts | 117 ++++++++++++++++++ ....ts => request_manager_middleware.test.ts} | 0 .../test/unit/transaction_middleware.test.ts | 76 ++++++++++++ 19 files changed, 574 insertions(+), 10 deletions(-) create mode 100644 packages/web3-eth/test/fixtures/transactions_data.ts create mode 100644 packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts rename tools/web3-plugin-example/src/{middleware.ts => request_manager_middleware.ts} (100%) create mode 100644 tools/web3-plugin-example/src/transaction_middleware.ts create mode 100644 tools/web3-plugin-example/src/transaction_middleware_plugin.ts create mode 100644 tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts rename tools/web3-plugin-example/test/unit/{middleware.test.ts => request_manager_middleware.test.ts} (100%) create mode 100644 tools/web3-plugin-example/test/unit/transaction_middleware.test.ts diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 0346e3f74a9..6c8e6a2a7e2 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -221,4 +221,8 @@ Documentation: - Set a try catch block if processesingError fails (#7022) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file diff --git a/packages/web3-core/src/web3_context.ts b/packages/web3-core/src/web3_context.ts index b50f8ba30f7..867f10f2350 100644 --- a/packages/web3-core/src/web3_context.ts +++ b/packages/web3-core/src/web3_context.ts @@ -219,6 +219,9 @@ export class Web3Context< newContextChild.setConfig({ [event.name]: event.newValue }); }); + // @ts-expect-error No index signature with a parameter of type 'string' was found on type 'Web3Context' + this[ContextRef.name] = newContextChild; + return newContextChild; } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 3d2d36b17c0..98dfb42b220 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -248,4 +248,10 @@ Documentation: - Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +- `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) +- WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) +- `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) \ No newline at end of file diff --git a/packages/web3-eth/src/rpc_method_wrappers.ts b/packages/web3-eth/src/rpc_method_wrappers.ts index 20e832be892..336aef3a23d 100644 --- a/packages/web3-eth/src/rpc_method_wrappers.ts +++ b/packages/web3-eth/src/rpc_method_wrappers.ts @@ -70,6 +70,7 @@ import { SendSignedTransactionOptions, SendTransactionEvents, SendTransactionOptions, + TransactionMiddleware, } from './types.js'; // eslint-disable-next-line import/no-cycle import { getTransactionFromOrToAttr } from './utils/transaction_builder.js'; @@ -544,13 +545,14 @@ export function sendTransaction< ResolveType = FormatType, >( web3Context: Web3Context, - transaction: + transactionObj: | Transaction | TransactionWithFromLocalWalletIndex | TransactionWithToLocalWalletIndex | TransactionWithFromAndToLocalWalletIndex, returnFormat: ReturnFormat, options: SendTransactionOptions = { checkRevertBeforeSending: true }, + transactionMiddleware?: TransactionMiddleware ): Web3PromiEvent> { const promiEvent = new Web3PromiEvent>( (resolve, reject) => { @@ -563,6 +565,12 @@ export function sendTransaction< returnFormat, }); + let transaction = {...transactionObj}; + + if(!isNullish(transactionMiddleware)){ + transaction = await transactionMiddleware.processTransaction(transaction); + } + let transactionFormatted: | Transaction | TransactionWithFromLocalWalletIndex diff --git a/packages/web3-eth/src/types.ts b/packages/web3-eth/src/types.ts index e1bba319d69..9ed49badb39 100644 --- a/packages/web3-eth/src/types.ts +++ b/packages/web3-eth/src/types.ts @@ -33,6 +33,9 @@ import { Numbers, Transaction, TransactionReceipt, + TransactionWithFromAndToLocalWalletIndex, + TransactionWithFromLocalWalletIndex, + TransactionWithToLocalWalletIndex, } from 'web3-types'; export type InternalTransaction = FormatType; @@ -88,3 +91,17 @@ export interface RevertReasonWithCustomError extends RevertReason { customErrorDecodedSignature: string; customErrorArguments: Record; } + +export type TransactionMiddlewareData = Transaction +| TransactionWithFromLocalWalletIndex +| TransactionWithToLocalWalletIndex +| TransactionWithFromAndToLocalWalletIndex; + +export interface TransactionMiddleware{ + // for transaction processing before signing + processTransaction( + transaction: TransactionMiddlewareData, + options?: { [key: string]: unknown }, + ): Promise; + +} \ No newline at end of file diff --git a/packages/web3-eth/src/web3_eth.ts b/packages/web3-eth/src/web3_eth.ts index 959a7d5eddc..abce5c2c317 100644 --- a/packages/web3-eth/src/web3_eth.ts +++ b/packages/web3-eth/src/web3_eth.ts @@ -48,7 +48,7 @@ import { toChecksumAddress, isNullish, ethUnitMap } from 'web3-utils'; import { ethRpcMethods } from 'web3-rpc-methods'; import * as rpcMethodsWrappers from './rpc_method_wrappers.js'; -import { SendTransactionOptions } from './types.js'; +import { SendTransactionOptions, TransactionMiddleware } from './types.js'; import { LogsSubscription, NewPendingTransactionsSubscription, @@ -99,6 +99,9 @@ export const registeredSubscriptions = { * ``` */ export class Web3Eth extends Web3Context { + + private transactionMiddleware?: TransactionMiddleware; + public constructor( providerOrContext?: SupportedProviders | Web3ContextInitOptions | string, ) { @@ -126,6 +129,14 @@ export class Web3Eth extends Web3Context. +*/ + +export const blockMockResult = { + "jsonrpc": "2.0", + "id": "a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f", + "result": { + "baseFeePerGas": "0x44dab2983", + "blobGasUsed": "0x20000", + "difficulty": "0x0", + "excessBlobGas": "0x1c0000", + "extraData": "0x407273796e636275696c646572", + "gasLimit": "0x1c9c380", + "gasUsed": "0xb7a086", + "hash": "0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95", + "logsBloom": "0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d", + "miner": "0x1f9090aae28b8a3dceadf281b0f12828e676c326", + "mixHash": "0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24", + "nonce": "0x0000000000000000", + "number": "0x131ad16", + "parentBeaconBlockRoot": "0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad", + "parentHash": "0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c", + "receiptsRoot": "0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0xcb90", + "stateRoot": "0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568", + "timestamp": "0x6661ab8b", + "totalDifficulty": "0xc70d815d562d3cfa955", + "transactions": [ + "0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41", + "0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93", + "0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b", + "0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061", + "0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7", + "0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca", + "0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9", + "0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2", + "0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b", + ], + "transactionsRoot": "0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607", + "uncles": [], + "withdrawals": [ + { + "address": "0xea97dc2523c0479484076660f150833e264c41e9", + "amount": "0x11b6d8c", + "index": "0x2dbe454", + "validatorIndex": "0x10f646" + }, + { + "address": "0xb3e84b6c6409826dc45432b655d8c9489a14a0d7", + "amount": "0x11b4ce2", + "index": "0x2dbe455", + "validatorIndex": "0x10f647" + }, + { + "address": "0x7e2a2fa2a064f693f0a55c5639476d913ff12d05", + "amount": "0x11ad733", + "index": "0x2dbe456", + "validatorIndex": "0x10f648" + }, + + ], + "withdrawalsRoot": "0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a" + } +}; + +export const receiptMockResult = { + "jsonrpc": "2.0", + "id": 1, + "result": { + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + // eslint-disable-next-line no-null/no-null + "contractAddress": null, + "cumulativeGasUsed": "0x8cae7a", + "effectiveGasPrice": "0x4c9bc2d65", + "from": "0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "gasUsed": "0xa145", + "logs": [ + { + "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + "data": "0x000000000000000000000000000000000000000000000000000000000016e360", + "logIndex": "0xdf", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00" + ], + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82" + } + ], + "logsBloom": "0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000", + "status": "0x1", + "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82", + "type": "0x2" + } +}; \ No newline at end of file diff --git a/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts new file mode 100644 index 00000000000..63dddbb759f --- /dev/null +++ b/packages/web3-eth/test/unit/rpc_method_wrappers/send_transaction_middleware.test.ts @@ -0,0 +1,98 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { Web3Context } from "web3-core"; +import { DEFAULT_RETURN_FORMAT, Web3EthExecutionAPI } from "web3-types"; +import {blockMockResult,receiptMockResult } from "../../fixtures/transactions_data"; +import { TransactionMiddleware, sendTransaction } from "../../../src"; + +const mockTransactionMiddleware: TransactionMiddleware = { + processTransaction: jest.fn(async (transaction) => { + const tx = {...transaction} + tx.data = '0x123'; + return Promise.resolve(tx)} +), +}; + +describe('sendTransaction', () => { + let web3Context: Web3Context; + + beforeEach(() => { + let blockNum = 0; + web3Context = new Web3Context('http://127.0.0.1:8545'); + + web3Context.requestManager.send = jest.fn(async (request) => { + blockNum += 1; + + if(request.method === 'eth_getBlockByNumber'){ + + return Promise.resolve(blockMockResult.result); + } + if(request.method === 'eth_call'){ + + return Promise.resolve("0x"); + } + if(request.method === 'eth_blockNumber'){ + + return Promise.resolve(blockNum.toString(16)); + } + if(request.method === 'eth_sendTransaction'){ + + return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + } + if (request.method === 'eth_getTransactionReceipt') { + return Promise.resolve(receiptMockResult.result); + } + + return Promise.resolve("Unknown Request" as any); + }); + }); + + afterEach(() => jest.resetAllMocks()); + + it('should call processTransaction when transactionMiddleware is provided', async () => { + const transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1' + }; + + await sendTransaction( + web3Context, + transaction, + DEFAULT_RETURN_FORMAT, + {}, + mockTransactionMiddleware, + ); + + expect(mockTransactionMiddleware.processTransaction).toHaveBeenCalledWith(transaction); + }); + + it('should not call processTransaction when transactionMiddleware is not provided', async () => { + const transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1' + }; + + await sendTransaction(web3Context, transaction, DEFAULT_RETURN_FORMAT); + + expect(mockTransactionMiddleware.processTransaction).not.toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts index c2f017b24cf..76d753bde4b 100644 --- a/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts +++ b/packages/web3-eth/test/unit/web3_eth_methods_with_parameters.test.ts @@ -17,7 +17,7 @@ along with web3.js. If not, see . import { ethRpcMethods } from 'web3-rpc-methods'; import { TransactionInfoAPI } from 'web3-types'; -import Web3Eth from '../../src/index'; +import Web3Eth, { TransactionMiddleware } from '../../src/index'; import * as rpcMethodWrappers from '../../src/rpc_method_wrappers'; import { getBlockNumberValidData, @@ -63,6 +63,20 @@ describe('web3_eth_methods_with_parameters', () => { web3Eth = new Web3Eth('http://127.0.0.1:8545'); }); + it('should set and unset the transactionMiddleware correctly', () => { + const mockTransactionMiddleware: TransactionMiddleware = { + processTransaction: jest.fn(), + }; + + web3Eth.setTransactionMiddleware(mockTransactionMiddleware); + + expect(web3Eth.getTransactionMiddleware()).toBe(mockTransactionMiddleware); + + web3Eth.setTransactionMiddleware(undefined as any); + + expect(web3Eth.getTransactionMiddleware()).toBeUndefined(); + }); + describe('should call RPC method with expected parameters', () => { describe('only has returnFormat parameter', () => { describe('getHashRate', () => { diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 896d0d884f0..c66601be9ed 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -268,4 +268,10 @@ Documentation: - Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +#### web3 + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file diff --git a/tools/web3-plugin-example/CHANGELOG.md b/tools/web3-plugin-example/CHANGELOG.md index 65e4434200c..636ba482bed 100644 --- a/tools/web3-plugin-example/CHANGELOG.md +++ b/tools/web3-plugin-example/CHANGELOG.md @@ -88,4 +88,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Dependencies updated -## [Unreleased] \ No newline at end of file +## [Unreleased] + +### Added + +Transaction middleware (#7088) \ No newline at end of file diff --git a/tools/web3-plugin-example/package.json b/tools/web3-plugin-example/package.json index 3832f5ef30d..2e85b5750ce 100644 --- a/tools/web3-plugin-example/package.json +++ b/tools/web3-plugin-example/package.json @@ -57,6 +57,7 @@ "web3-eth-abi": ">= 4.1.1 < 5", "web3-eth-contract": ">= 4.0.5 < 5", "web3-types": ">= 1.1.1 < 5", - "web3-utils": ">= 4.0.5 < 5" + "web3-utils": ">= 4.0.5 < 5", + "web3-eth": ">= 4.7.0 < 5" } } diff --git a/tools/web3-plugin-example/src/custom_rpc_methods.ts b/tools/web3-plugin-example/src/custom_rpc_methods.ts index ed1c2fbee23..d5ff583ddf5 100644 --- a/tools/web3-plugin-example/src/custom_rpc_methods.ts +++ b/tools/web3-plugin-example/src/custom_rpc_methods.ts @@ -18,7 +18,7 @@ import { Web3PluginBase } from 'web3-core'; // eslint-disable-next-line require-extensions/require-extensions import { Web3Context } from './reexported_web3_context'; // eslint-disable-next-line require-extensions/require-extensions -import { Web3Middleware } from './middleware'; +import { Web3Middleware } from './request_manager_middleware'; type CustomRpcApi = { custom_rpc_method: () => string; diff --git a/tools/web3-plugin-example/src/middleware.ts b/tools/web3-plugin-example/src/request_manager_middleware.ts similarity index 100% rename from tools/web3-plugin-example/src/middleware.ts rename to tools/web3-plugin-example/src/request_manager_middleware.ts diff --git a/tools/web3-plugin-example/src/transaction_middleware.ts b/tools/web3-plugin-example/src/transaction_middleware.ts new file mode 100644 index 00000000000..d38eec8127b --- /dev/null +++ b/tools/web3-plugin-example/src/transaction_middleware.ts @@ -0,0 +1,38 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { TransactionMiddleware, TransactionMiddlewareData } from "web3-eth"; + +// Sample Transaction Middleware +export class Web3TransactionMiddleware implements TransactionMiddleware { + + // eslint-disable-next-line class-methods-use-this + public async processTransaction(transaction: TransactionMiddlewareData, + _options?: { [key: string]: unknown } | undefined): + + Promise { + + // eslint-disable-next-line prefer-const + let txObj = { ...transaction }; + + // Add your logic here for transaction modification + txObj.data = '0x123'; + + return Promise.resolve(txObj); + } + +} diff --git a/tools/web3-plugin-example/src/transaction_middleware_plugin.ts b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts new file mode 100644 index 00000000000..3dd86ed7e26 --- /dev/null +++ b/tools/web3-plugin-example/src/transaction_middleware_plugin.ts @@ -0,0 +1,44 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3PluginBase } from 'web3-core'; +// eslint-disable-next-line require-extensions/require-extensions +import { Web3Context } from './reexported_web3_context'; +// eslint-disable-next-line require-extensions/require-extensions +import { Web3TransactionMiddleware } from './transaction_middleware'; + +// Sample Transaction middleware plugin +export class TransactionMiddlewarePlugin extends Web3PluginBase { + public pluginNamespace = 'TransactionsPlugIn'; + public txMiddleware: Web3TransactionMiddleware; + + public constructor() { + super(); + this.txMiddleware = new Web3TransactionMiddleware(); + } + + public link(parentContext: Web3Context): void { + + if (this.txMiddleware){ + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + (parentContext as any).Web3Eth.setTransactionMiddleware(this.txMiddleware); + } + + super.link(parentContext); + } + +} + diff --git a/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts b/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts new file mode 100644 index 00000000000..189e2135ae4 --- /dev/null +++ b/tools/web3-plugin-example/test/unit/fixtures/transactions_data.ts @@ -0,0 +1,117 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +export const blockMockResult = { + "jsonrpc": "2.0", + "id": "a40a81fa-1f8b-4bb2-a0ad-eef9b6d4636f", + "result": { + "baseFeePerGas": "0x44dab2983", + "blobGasUsed": "0x20000", + "difficulty": "0x0", + "excessBlobGas": "0x1c0000", + "extraData": "0x407273796e636275696c646572", + "gasLimit": "0x1c9c380", + "gasUsed": "0xb7a086", + "hash": "0xf2b1729965179032b17165678a1a212fa31cb008e30f4011ffe8ebdddbd02b95", + "logsBloom": "0xc3a70590c1c62524173d1892e33888067101934dc0891c2c9a898252b6f320215084a48906452960820188d32bba6fb82ec989018a0268603a00a4c6432a11276c9a038c676938eb68bc436c9905a9a1b08d238fb4458f48498215808bec81112e2a3a54869ff22422a8e491093da8a40f601d198417041cd22f799f9048865006e0b069ab049b852442b310396248088145e2810f230f9a44000c6868bc73e9afa8832a8ac92fd609007ac53c0a9cba0645ce298080184624e8040831dbc331f5e618072407050250021b3210e542781183a612d4618c1244000d421a6ca9c01a57e86a085402c55ab413f840a001e7117894d0469e20c2304a9655e344f60d", + "miner": "0x1f9090aae28b8a3dceadf281b0f12828e676c326", + "mixHash": "0x787ab1d511b72df60a705bb4cfc4e92e2f9d203e3e007ae3a0f757425951ca24", + "nonce": "0x0000000000000000", + "number": "0x131ad16", + "parentBeaconBlockRoot": "0x03bbca9fd0c7a0a020de04287f489112c79bc268220e9ff8e18957cd0d5c3cad", + "parentHash": "0xb1d8fa7b8346421d373a6d4c28575155516cea17c12a3df7201170c9e561b38c", + "receiptsRoot": "0x4ec500bdcd761ad505b2a989156c9a9628058d415acc93d800487c7c76308c59", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0xcb90", + "stateRoot": "0xafbb8743c0a5f4740e322217cb1f2780ee5c57c32bcd04e9256b09efc1a70568", + "timestamp": "0x6661ab8b", + "totalDifficulty": "0xc70d815d562d3cfa955", + "transactions": [ + "0x589956b75d19dbaf9911f246c23d4b3327ef234872ec1931c419041b23eb5b41", + "0x4d3793f20c25979bd329cafdd889ba6be015cfc999acce8642d6e757b5192e93", + "0x5ba5618ca5a14bab50862255dc69726a498346f9832bd0fd1394e8834e56790b", + "0x6df9678f350db7e30afc930b7246bf1c144b9acb7fd1d25d7e107d550ed5a061", + "0xb8f48ff2876cc393725ea4162421754dfb74ff2364a12d4d3de2c6269f1958c7", + "0x2e5cf7c0607025038b6ccd871dc9ce85af686fd5fa2c82e605198af9afa92cca", + "0x307fb855836feff5d8d0969fa4a44d3c6ae31d335da6577f48f9496d6fe9e0b9", + "0x1362bed1aa8a30d28b7b76c35c2a8601b257058beffa9490dcb20de12bcb15b2", + "0x234c7cc346c204022b2e5ead6d2e8c02317aeb0ec5ca82bd97c2b5d5e59a280b", + ], + "transactionsRoot": "0xc21a4d667b5f841538430b1e2c002c598f2178628ad1d61ea2fda462d1216607", + "uncles": [], + "withdrawals": [ + { + "address": "0xea97dc2523c0479484076660f150833e264c41e9", + "amount": "0x11b6d8c", + "index": "0x2dbe454", + "validatorIndex": "0x10f646" + }, + { + "address": "0xb3e84b6c6409826dc45432b655d8c9489a14a0d7", + "amount": "0x11b4ce2", + "index": "0x2dbe455", + "validatorIndex": "0x10f647" + }, + { + "address": "0x7e2a2fa2a064f693f0a55c5639476d913ff12d05", + "amount": "0x11ad733", + "index": "0x2dbe456", + "validatorIndex": "0x10f648" + }, + + ], + "withdrawalsRoot": "0x2914fa2f5ed93880ed45b58e8f6d14f20c645988400d83c59109964e2053fe1a" + } +}; + +export const receiptMockResult = { + "jsonrpc": "2.0", + "id": 1, + "result": { + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + // eslint-disable-next-line no-null/no-null + "contractAddress": null, + "cumulativeGasUsed": "0x8cae7a", + "effectiveGasPrice": "0x4c9bc2d65", + "from": "0xab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "gasUsed": "0xa145", + "logs": [ + { + "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "blockHash": "0xf4ad699b98241caf3930779b7d919a77f1727e67cef6ed1ce2a4c655ba812d54", + "blockNumber": "0x131ad35", + "data": "0x000000000000000000000000000000000000000000000000000000000016e360", + "logIndex": "0xdf", + "removed": false, + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x000000000000000000000000ab6fd3a7c6ce9db945889cd018e028e055f3bc2e", + "0x00000000000000000000000051112f9f08a2174fe3fc96aad8f07e82d1cccd00" + ], + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82" + } + ], + "logsBloom": "0x00000000000000000000000002000000000000000000000000000000004000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000100000000000000000000000000080000000000000000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000400000000000000000000000", + "status": "0x1", + "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", + "transactionHash": "0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f", + "transactionIndex": "0x82", + "type": "0x2" + } +}; \ No newline at end of file diff --git a/tools/web3-plugin-example/test/unit/middleware.test.ts b/tools/web3-plugin-example/test/unit/request_manager_middleware.test.ts similarity index 100% rename from tools/web3-plugin-example/test/unit/middleware.test.ts rename to tools/web3-plugin-example/test/unit/request_manager_middleware.test.ts diff --git a/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts b/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts new file mode 100644 index 00000000000..2009e028283 --- /dev/null +++ b/tools/web3-plugin-example/test/unit/transaction_middleware.test.ts @@ -0,0 +1,76 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { Web3, Transaction } from 'web3'; +import { TransactionMiddlewarePlugin } from '../../src/transaction_middleware_plugin'; +import { blockMockResult, receiptMockResult } from './fixtures/transactions_data'; + +describe('Transaction Middleware', () => { + + // This will allow Transaction modification before signing and gas estimations + it('should modify transaction before signing', async () => { + const web3 = new Web3('http://127.0.0.1:8545'); + const plugin = new TransactionMiddlewarePlugin(); + + /// Mock block starts - Mock web3 internal calls for test + let blockNum = 1000; + + web3.requestManager.send = jest.fn(async (request) => { + blockNum += 1; + + if(request.method === 'eth_getBlockByNumber'){ + + return Promise.resolve(blockMockResult.result); + } + if(request.method === 'eth_call'){ + + return Promise.resolve("0x"); + } + if(request.method === 'eth_blockNumber'){ + + return Promise.resolve(blockNum.toString(16)); + } + if(request.method === 'eth_sendTransaction'){ + + // Test that middleware modified transaction + // eslint-disable-next-line jest/no-conditional-expect + expect((request.params as any)[0].data).toBe("0x123"); + + return Promise.resolve("0xdf7756865c2056ce34c4eabe4eff42ad251a9f920a1c620c00b4ea0988731d3f"); + } + if (request.method === 'eth_getTransactionReceipt') { + return Promise.resolve(receiptMockResult.result); + } + + return Promise.resolve("Unknown Request" as any); + }); + + /// Mock block ends here + + web3.registerPlugin(plugin); + + const transaction: Transaction = { + from: '0x6E599DA0bfF7A6598AC1224E4985430Bf16458a4', + to: '0x6f1DF96865D09d21e8f3f9a7fbA3b17A11c7C53C', + value: '0x1', + data: '0x1' + }; + + await web3.eth.sendTransaction(transaction as any); + + }); +}); From 7a51c33315fea9bc3b8a7daa0d5d4f08dcac12af Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 11 Jun 2024 09:59:16 -0400 Subject: [PATCH 22/25] add test coverage to web3-core (#7091) * add test coverage to web3-core * make types compitable * update * update * update types * update types * update * update tests --- .../web3-core/src/web3_request_manager.ts | 10 -- packages/web3-core/src/web3_subscriptions.ts | 11 -- .../unit/fixtures/custom_transaction_type.ts | 73 +++++++++++ .../unit/fixtures/example_subscription.ts | 5 +- .../fixtures/example_subscription_build.ts | 28 +++++ .../web3-core/test/unit/formatters.test.ts | 118 +++++++++++++++++- .../web3-core/test/unit/web3_config.test.ts | 80 +++++++++++- .../web3-core/test/unit/web3_context.test.ts | 115 ++++++++++++++++- .../test/unit/web3_request_manager.test.ts | 60 +++++++++ .../test/unit/web3_subscription.test.ts | 92 +++++++++++++- .../unit/web3_subscription_manager.test.ts | 44 ++++++- packages/web3-types/src/json_rpc_types.ts | 6 +- 12 files changed, 611 insertions(+), 31 deletions(-) create mode 100644 packages/web3-core/test/unit/fixtures/custom_transaction_type.ts create mode 100644 packages/web3-core/test/unit/fixtures/example_subscription_build.ts diff --git a/packages/web3-core/src/web3_request_manager.ts b/packages/web3-core/src/web3_request_manager.ts index 1cbe9377988..21783229a5f 100644 --- a/packages/web3-core/src/web3_request_manager.ts +++ b/packages/web3-core/src/web3_request_manager.ts @@ -429,7 +429,6 @@ export class Web3RequestManager< ) { return this._buildResponse(payload, response, error); } - if (jsonRpc.isBatchRequest(payload) && !Array.isArray(response)) { throw new ResponseError(response, 'Got normal response for a batch request.'); } @@ -438,15 +437,6 @@ export class Web3RequestManager< throw new ResponseError(response, 'Got batch response for a normal request.'); } - if ( - (jsonRpc.isResponseWithError(response) || jsonRpc.isResponseWithResult(response)) && - !jsonRpc.isBatchRequest(payload) - ) { - if (response.id && payload.id !== response.id) { - throw new InvalidResponseError(response); - } - } - throw new ResponseError(response, 'Invalid response'); } diff --git a/packages/web3-core/src/web3_subscriptions.ts b/packages/web3-core/src/web3_subscriptions.ts index 3cf4cee9f50..21cd4fe21fe 100644 --- a/packages/web3-core/src/web3_subscriptions.ts +++ b/packages/web3-core/src/web3_subscriptions.ts @@ -30,7 +30,6 @@ import { Web3APISpec, } from 'web3-types'; import { jsonRpc } from 'web3-utils'; -import { SubscriptionError } from 'web3-errors'; // eslint-disable-next-line import/no-cycle import { Web3SubscriptionManager } from './web3_subscription_manager.js'; @@ -82,16 +81,6 @@ export abstract class Web3Subscription< super(); const { requestManager } = options as { requestManager: Web3RequestManager }; const { subscriptionManager } = options as { subscriptionManager: Web3SubscriptionManager }; - if (requestManager && subscriptionManager) { - throw new SubscriptionError( - 'Only requestManager or subscriptionManager should be provided at Subscription constructor', - ); - } - if (!requestManager && !subscriptionManager) { - throw new SubscriptionError( - 'Either requestManager or subscriptionManager should be provided at Subscription constructor', - ); - } if (requestManager) { // eslint-disable-next-line deprecation/deprecation this._subscriptionManager = new Web3SubscriptionManager(requestManager, {}, true); diff --git a/packages/web3-core/test/unit/fixtures/custom_transaction_type.ts b/packages/web3-core/test/unit/fixtures/custom_transaction_type.ts new file mode 100644 index 00000000000..12e4789a92d --- /dev/null +++ b/packages/web3-core/test/unit/fixtures/custom_transaction_type.ts @@ -0,0 +1,73 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ + +import { + BaseTransaction, + TxValuesArray, + AccessListEIP2930ValuesArray, + FeeMarketEIP1559ValuesArray, + JsonTx, +} from 'web3-eth-accounts'; + +export class CustomTransactionType extends BaseTransaction { + // eslint-disable-next-line class-methods-use-this + public getUpfrontCost(): bigint { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public raw(): TxValuesArray | AccessListEIP2930ValuesArray | FeeMarketEIP1559ValuesArray { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public serialize(): Uint8Array { + throw new Error('Method not implemented.'); + } + public getMessageToSign(hashMessage: false): Uint8Array | Uint8Array[]; + public getMessageToSign(hashMessage?: true | undefined): Uint8Array; + // eslint-disable-next-line class-methods-use-this + public getMessageToSign(): Uint8Array | Uint8Array[] { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public hash(): Uint8Array { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public getMessageToVerifySignature(): Uint8Array { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public getSenderPublicKey(): Uint8Array { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + public toJSON(): JsonTx { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + protected _processSignature(): unknown { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility, class-methods-use-this + public errorStr(): string { + throw new Error('Method not implemented.'); + } + // eslint-disable-next-line class-methods-use-this + protected _errorMsg(): string { + throw new Error('Method not implemented.'); + } +} diff --git a/packages/web3-core/test/unit/fixtures/example_subscription.ts b/packages/web3-core/test/unit/fixtures/example_subscription.ts index ee23ce2311e..019d4ccccc9 100644 --- a/packages/web3-core/test/unit/fixtures/example_subscription.ts +++ b/packages/web3-core/test/unit/fixtures/example_subscription.ts @@ -14,7 +14,7 @@ GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ - +import { DataFormat } from 'web3-types'; import { Web3Subscription } from '../../../src'; export class ExampleSubscription extends Web3Subscription< @@ -26,4 +26,7 @@ export class ExampleSubscription extends Web3Subscription< protected _buildSubscriptionParams() { return ['newHeads']; } + public getReturnFormat(): DataFormat { + return this.returnFormat; + } } diff --git a/packages/web3-core/test/unit/fixtures/example_subscription_build.ts b/packages/web3-core/test/unit/fixtures/example_subscription_build.ts new file mode 100644 index 00000000000..88fea953349 --- /dev/null +++ b/packages/web3-core/test/unit/fixtures/example_subscription_build.ts @@ -0,0 +1,28 @@ +/* +This file is part of web3.js. + +web3.js is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +web3.js is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with web3.js. If not, see . +*/ +import { Web3Subscription } from '../../../src'; + +// subscription class that exposes buildSubscriptionParams +export class BuildSubscription extends Web3Subscription< + { data: string }, + { param1: string }, + { eth_subscribe: (newHeads: string) => void } +> { + public buildSubscriptionParams() { + this._buildSubscriptionParams(); + } +} diff --git a/packages/web3-core/test/unit/formatters.test.ts b/packages/web3-core/test/unit/formatters.test.ts index 105fb4fcf45..022d87f65cb 100644 --- a/packages/web3-core/test/unit/formatters.test.ts +++ b/packages/web3-core/test/unit/formatters.test.ts @@ -16,8 +16,9 @@ along with web3.js. If not, see . */ import * as utils from 'web3-utils'; -import { BlockTags } from 'web3-types'; +import { BlockTags, TransactionInput, Filter } from 'web3-types'; import { Iban } from 'web3-eth-iban'; +import { FormatterError } from 'web3-errors'; import { inputAddressFormatter, inputBlockNumberFormatter, @@ -268,6 +269,121 @@ describe('formatters', () => { ); }); + describe('inputCallFormatter', () => { + let txInput: any; + + beforeEach(() => { + jest.spyOn(utils, 'isAddress').mockReturnValue(true); + txInput = { + to: '0xabcd', + }; + }); + + it('should format "to" address if provided', () => { + expect(formatters.inputCallFormatter({ ...txInput, to: '0xABCD' })).toEqual( + expect.objectContaining({ to: '0xabcd' }), + ); + }); + + it('should format "from" if defaultAddress is provided', () => { + expect(formatters.inputCallFormatter({ ...txInput, to: '0xABCD' }, '0xABCDE')).toEqual( + expect.objectContaining({ from: '0xabcde', to: '0xabcd' }), + ); + }); + }); + + describe('inputTransactionFormatter', () => { + let txInput: any; + + beforeEach(() => { + jest.spyOn(utils, 'isAddress').mockReturnValue(true); + txInput = { + to: '0xabcd', + }; + }); + it('should format and populate "from"', () => { + expect( + formatters.inputTransactionFormatter({ ...txInput, to: '0xabcd', from: '0xABCDE' }), + ).toEqual(expect.objectContaining({ from: '0xabcde', to: '0xabcd' })); + }); + + it('should throw an error when from is undefined', () => { + expect(() => formatters.inputTransactionFormatter({ ...txInput })).toThrow( + new FormatterError('The send transactions "from" field must be defined!'), + ); + }); + }); + + describe('outputTransactionFormatter', () => { + it('should correctly format blockNumber from hex to number', () => { + const txInput: TransactionInput = { + to: '0x1234567890abcdef', + from: '0xabcdef1234567890', + gas: '0x123456', + gasPrice: '0x987654321', + nonce: '0x1', + value: '0x9876543210', + blockNumber: '0x123', + transactionIndex: '0x1', + maxFeePerGas: '0x87654321', + maxPriorityFeePerGas: '0x7654321', + type: '0x1', + }; + + const formattedTxOutput = formatters.outputTransactionFormatter(txInput); + // should return the mocked values; + expect(formattedTxOutput.blockNumber).toBe(123); + expect(formattedTxOutput.to).toBe('toChecksumAddress'); + expect(formattedTxOutput.from).toBe('toChecksumAddress'); + expect(formattedTxOutput.gas).toBe(123); + expect(formattedTxOutput.nonce).toBe(123); + expect(formattedTxOutput.transactionIndex).toBe(123); + expect(formattedTxOutput.value).toBe(12345); + expect(formattedTxOutput.maxFeePerGas).toBe(12345); + expect(formattedTxOutput.maxPriorityFeePerGas).toBe(12345); + expect(formattedTxOutput.type).toBe(123); + }); + + it('should make "to" property undefined', () => { + const txInput = { gas: '0x', nonce: '1', value: '0x' }; + const formattedTxOutput = formatters.outputTransactionFormatter(txInput); + + expect(formattedTxOutput.to).toBeUndefined(); + }); + }); + + describe('inputLogFormatter', () => { + beforeAll(() => { + const actualUtils = jest.requireActual('web3-utils'); + jest.spyOn(utils, 'mergeDeep').mockImplementation(actualUtils.mergeDeep); + }); + it('should correctly format a filter with all fields provided', () => { + const filter: Filter = { + fromBlock: '0x1', + toBlock: '0x2', + address: '0x1234567890abcdef1234567890abcdef12345678', + topics: ['0x123', ['0x456', '0x789']], + }; + + const formattedFilter = formatters.inputLogFormatter(filter); + + expect(formattedFilter.fromBlock).toBe('0x1'); + expect(formattedFilter.toBlock).toBe('0x2'); + expect(formattedFilter.address).toBe('0x1234567890abcdef1234567890abcdef12345678'); + expect(formattedFilter.topics).toEqual(['0x123', ['0x456', '0x789']]); + }); + it('should correctly format a filter with no fromBlock', () => { + const filter: Filter = { + address: ['0x123', '0x222'], + }; + + const formattedFilter = formatters.inputLogFormatter(filter); + + expect(formattedFilter.fromBlock).toBe('latest'); + expect(formattedFilter.address).toEqual(['0x123', '0x222']); + }); + }); + describe('outputLogFormatter', () => { it('should set log id from "blockHash", "transactionHash" and "logIndex"', () => { const result = outputLogFormatter({ diff --git a/packages/web3-core/test/unit/web3_config.test.ts b/packages/web3-core/test/unit/web3_config.test.ts index 0391eec851a..bd250d6386a 100644 --- a/packages/web3-core/test/unit/web3_config.test.ts +++ b/packages/web3-core/test/unit/web3_config.test.ts @@ -16,7 +16,8 @@ along with web3.js. If not, see . */ import { toHex } from 'web3-utils'; -import { DEFAULT_RETURN_FORMAT } from 'web3-types'; +import { DEFAULT_RETURN_FORMAT, Hardfork, ValidChains } from 'web3-types'; +import { ConfigHardforkMismatchError, ConfigChainMismatchError } from 'web3-errors'; import { Web3Config, Web3ConfigEvent } from '../../src/web3_config'; class MyConfigObject extends Web3Config {} @@ -46,6 +47,8 @@ const defaultConfig = { defaultTransactionType: '0x2', defaultMaxPriorityFeePerGas: toHex(2500000000), defaultReturnFormat: DEFAULT_RETURN_FORMAT, + transactionBuilder: undefined, + transactionTypeParser: undefined, }; const setValue = { string: 'newValue', @@ -123,6 +126,81 @@ describe('Web3Config', () => { ); }); + it('should throw when val does not match config.defaultCommon.defaultHardFork', () => { + const obj = new MyConfigObject(); + const defaultCommon = { + defaultHardfork: 'london' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + }; + obj.setConfig({ + defaultCommon, + }); + const newDefaultCommon = { + hardfork: 'berlin' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + }; + expect(() => { + obj.defaultCommon = newDefaultCommon; + }).toThrow( + new ConfigHardforkMismatchError( + defaultCommon.defaultHardfork, + newDefaultCommon.hardfork, + ), + ); + }); + + it('defaulthardfork should throw when val does not match config.defaultCommon.hardfork', () => { + const obj = new MyConfigObject(); + const defaultCommon = { + hardfork: 'london' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + }; + const hardfork = 'berlin'; + obj.setConfig({ + defaultCommon, + }); + expect(() => { + obj.defaultHardfork = hardfork; + }).toThrow(new ConfigHardforkMismatchError(defaultCommon.hardfork, hardfork)); + }); + + it('should throw when val does not match config.defaultChain', () => { + const obj = new MyConfigObject(); + const defaultCommon = { + defaultHardfork: 'london' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + defaultChain: 'mainnet', + }; + obj.setConfig({ + defaultCommon, + }); + const newDefaultCommon = { + hardfork: 'london' as Hardfork, + customChain: { + networkId: 1, + chainId: 1, + }, + baseChain: 'sepolia' as ValidChains, + }; + expect(() => { + obj.defaultCommon = newDefaultCommon; + }).toThrow( + new ConfigChainMismatchError(defaultCommon.defaultChain, newDefaultCommon.baseChain), + ); + }); + it('Updating transactionPollingInterval should update transactionReceiptPollingInterval and transactionConfirmationPollingInterval', () => { const obj = new MyConfigObject(); const configChange = jest.fn(); diff --git a/packages/web3-core/test/unit/web3_context.test.ts b/packages/web3-core/test/unit/web3_context.test.ts index c235a06cb83..b50c98e8661 100644 --- a/packages/web3-core/test/unit/web3_context.test.ts +++ b/packages/web3-core/test/unit/web3_context.test.ts @@ -24,10 +24,14 @@ import { JsonRpcResponse, Web3APIMethod, Web3APIReturnType, + Web3AccountProvider, + Web3BaseWalletAccount, + Web3BaseWallet, } from 'web3-types'; -import { Web3Context, Web3PluginBase } from '../../src/web3_context'; +import { Web3Context, Web3PluginBase, Web3ContextObject } from '../../src/web3_context'; import { Web3RequestManager } from '../../src/web3_request_manager'; import { RequestManagerMiddleware } from '../../src/types'; +import { CustomTransactionType } from './fixtures/custom_transaction_type'; // eslint-disable-next-line @typescript-eslint/ban-types class Context1 extends Web3Context<{}> {} @@ -64,13 +68,30 @@ describe('Web3Context', () => { expect(context.currentProvider).toBeInstanceOf(HttpProvider); }); + it('should return undefined when getting givenprovider', () => { + const context = new Web3Context('http://test.com'); + expect(context.givenProvider).toBeUndefined(); + }); it('should set return current provider for the request manager', () => { const context = new Web3Context('http://test.com'); - context.currentProvider = 'http://test/abc'; expect(context.currentProvider).toBeInstanceOf(HttpProvider); }); + it('should set httpProvider', () => { + const context = new Web3Context(); + const url = 'http://test/abc'; + context.setProvider(url); + const httpProvider = new HttpProvider(url); + expect(context.provider).toEqual(httpProvider); + }); + + it('get batch request', () => { + const context = new Web3Context(); + const BatchRequestClass = context.BatchRequest; + + expect(new BatchRequestClass()).toBeInstanceOf(context.BatchRequest); + }); it('should set middleware for the request manager', () => { const context = new Web3Context('http://test.com'); @@ -92,6 +113,82 @@ describe('Web3Context', () => { context.setRequestManagerMiddleware(middleware); expect(context.requestManager.middleware).toEqual(middleware); }); + it('should instantiate a new Web3Context object with provided context object', () => { + const config = { defaultNetworkId: 'my-network-id', defaultHardfork: 'my-fork' }; + const context = { + provider: 'http://test.com', + config, + } as Web3ContextObject; + const newContext = Web3Context.fromContextObject(context); + expect(newContext.currentProvider).toBeInstanceOf(HttpProvider); + expect(newContext.requestManager).toBeInstanceOf(Web3RequestManager); + expect(newContext.config.defaultHardfork).toEqual(config.defaultHardfork); + expect(newContext.config.defaultNetworkId).toEqual(config.defaultNetworkId); + }); + + describe('accountsProvider', () => { + const createAccountProvider = (): Web3AccountProvider => { + const accountProvider = { + privateKeyToAccount: jest.fn().mockImplementation(() => { + return ''; + }), + decrypt: jest.fn(), + create: jest.fn().mockImplementation(() => { + return ''; + }), + }; + return accountProvider; + }; + const accountProvider = createAccountProvider(); + + class WalletExample< + T extends Web3BaseWalletAccount = Web3BaseWalletAccount, + > extends Web3BaseWallet { + public create = jest.fn(() => this); + public add = jest.fn(() => this); + public get = jest.fn(() => { + return { + address: 'mockAddress', + privateKey: 'mockPrivateKey', + signTransaction: jest.fn(), + sign: jest.fn(), + encrypt: jest.fn(), + } as unknown as T; + }); + public remove = jest.fn(() => true); + public clear = jest.fn(() => this); + public encrypt = jest.fn(async () => Promise.resolve([])); + public decrypt = jest.fn(); + public save = jest.fn(); + public load = jest.fn(); + } + + const wallet = new WalletExample(accountProvider); + it('should set wallet in context', () => { + const context = new Web3Context({ + provider: 'http://test.com', + wallet, + }); + + expect(context.wallet).toEqual(wallet); + }); + it('should set the Accountsprovider when creating new context', () => { + const context = new Web3Context({ + provider: 'http://test.com', + accountProvider, + }); + + expect(context.accountProvider).toEqual(accountProvider); + }); + + it('should set wallet', () => { + const context = new Web3Context({ + provider: 'http://test.com', + wallet, + }); + expect(context.wallet).toEqual(wallet); + }); + }); }); describe('getContextObject', () => { @@ -255,6 +352,20 @@ describe('Web3Context', () => { }); describe('registerPlugin', () => { + it('should create a new type using registerNewTransactionType on a custom plugin', () => { + const context = new Context1('http://test/abc'); + const pluginNamespace = 'plugin'; + + class Plugin extends Web3PluginBase { + public constructor() { + super(); + this.registerNewTransactionType(3, CustomTransactionType); + } + public pluginNamespace = pluginNamespace; + } + + expect(() => context.registerPlugin(new Plugin())).not.toThrow(); + }); it('should throw ExistingPluginNamespaceError', () => { const context = new Context1('http://test/abc'); const pluginNamespace = 'plugin'; diff --git a/packages/web3-core/test/unit/web3_request_manager.test.ts b/packages/web3-core/test/unit/web3_request_manager.test.ts index 2db8c010fd8..9bbad51fdc9 100644 --- a/packages/web3-core/test/unit/web3_request_manager.test.ts +++ b/packages/web3-core/test/unit/web3_request_manager.test.ts @@ -730,6 +730,66 @@ describe('Web3RequestManager', () => { expect(myProvider.request).toHaveBeenCalledTimes(1); expect(myProvider.request).toHaveBeenCalledWith(payload); }); + it('should throw an error when payload batch request and response is not an array', async () => { + jest.spyOn(jsonRpc, 'toPayload').mockReturnValue([ + { method: 'my_method', params: [], id: 1, jsonrpc: '2.0' }, + ]); + const manager = new Web3RequestManager(); + + const pr = new Promise(resolve => { + resolve({ response: 'random' }); + }); + const myProvider = { + request: jest.fn().mockImplementation(async () => pr), + } as any; + manager.setProvider(myProvider); + + await expect(manager.send(request)).rejects.toThrow(); + + jest.clearAllMocks(); + }); + it('should throw an error when payload batch request is an array and response is not', async () => { + jest.spyOn(jsonRpc, 'toPayload').mockReturnValue({ + method: 'my_method', + params: [], + id: 1, + jsonrpc: '2.0', + }); + const manager = new Web3RequestManager(); + + const pr = new Promise(resolve => { + resolve([{ response: 'unknown response' }, { response: 'unknown response' }]); + }); + const myProvider = { + request: jest.fn().mockImplementation(async () => pr), + } as any; + manager.setProvider(myProvider); + + await expect(manager.send(request)).rejects.toThrow(); + + jest.clearAllMocks(); + }); + it('should throw an when invalid response', async () => { + jest.spyOn(jsonRpc, 'toPayload').mockReturnValue({ + method: 'my_method', + params: [], + id: 1, + jsonrpc: '2.0', + }); + const manager = new Web3RequestManager(); + + const pr = new Promise(resolve => { + resolve({ response: 'unknown response' }); + }); + const myProvider = { + request: jest.fn().mockImplementation(async () => pr), + } as any; + manager.setProvider(myProvider); + + await expect(manager.send(request)).rejects.toThrow(); + + jest.clearAllMocks(); + }); }); describe('legacy-request-provider', () => { diff --git a/packages/web3-core/test/unit/web3_subscription.test.ts b/packages/web3-core/test/unit/web3_subscription.test.ts index cab940b0f00..f04a8850af1 100644 --- a/packages/web3-core/test/unit/web3_subscription.test.ts +++ b/packages/web3-core/test/unit/web3_subscription.test.ts @@ -14,9 +14,10 @@ GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ - +import { JsonRpcNotification, Log, DEFAULT_RETURN_FORMAT } from 'web3-types'; import { Web3SubscriptionManager } from '../../src'; import { ExampleSubscription } from './fixtures/example_subscription'; +import { BuildSubscription } from './fixtures/example_subscription_build'; const subscriptions = { example: ExampleSubscription as never }; @@ -81,6 +82,10 @@ describe('Web3Subscription', () => { expect.any(Function), ); }); + + it('should return returnFormat', () => { + expect(sub.getReturnFormat()).toBe(DEFAULT_RETURN_FORMAT); + }); }); describe('unsubscribe', () => { @@ -89,6 +94,9 @@ describe('Web3Subscription', () => { sub['_id'] = 'sub-id'; subscriptionManager.subscriptions.set('sub-id', sub); }); + afterEach(() => { + jest.clearAllMocks(); + }); it('should invoke request manager to unsubscribe', async () => { await sub.unsubscribe(); @@ -105,6 +113,28 @@ describe('Web3Subscription', () => { await sub.unsubscribe(); expect(sub.id).toBeUndefined(); }); + it('should only call removeSubscription once after calling unsubscribe twice', async () => { + jest.spyOn(subscriptionManager, 'removeSubscription').mockImplementation(); + const newSub = new ExampleSubscription({ param1: 'value' }, { subscriptionManager }); + expect(newSub.id).toBeUndefined(); + await newSub.unsubscribe(); + expect(subscriptionManager.removeSubscription).toHaveBeenCalledTimes(0); + }); + }); + + describe('resubscribe', () => { + beforeEach(() => { + sub = new ExampleSubscription({ param1: 'value' }, { subscriptionManager }); + sub['_id'] = 'sub-id'; + subscriptionManager.subscriptions.set('sub-id', sub); + }); + it('should resubscribe', async () => { + jest.spyOn(sub, 'subscribe').mockImplementation(); + jest.spyOn(sub, 'unsubscribe').mockImplementation(); + await sub.resubscribe(); + expect(sub.subscribe).toHaveBeenCalledTimes(1); + expect(sub.unsubscribe).toHaveBeenCalledTimes(1); + }); }); }); @@ -156,6 +186,15 @@ describe('Web3Subscription without subscription manager - (deprecated)', () => { expect.any(Function), ); }); + it('should listen on error', () => { + const error = new Error(''); + const errorSpy = jest.fn(); + sub.on('error', errorSpy); + sub._processSubscriptionError(error); + + expect(errorSpy).toHaveBeenCalledTimes(1); + expect(errorSpy).toHaveBeenCalledWith(error); + }); }); describe('unsubscribe', () => { @@ -181,4 +220,55 @@ describe('Web3Subscription without subscription manager - (deprecated)', () => { expect(sub.id).toBeUndefined(); }); }); + + describe('lastblock', () => { + let subscriptionManager: Web3SubscriptionManager; + beforeEach(() => { + subscriptionManager = new Web3SubscriptionManager(requestManager, subscriptions); + sub = new ExampleSubscription({ param1: 'value' }, { subscriptionManager }); + sub['_id'] = 'sub-id'; + }); + it('should get last block', () => { + expect(sub.lastBlock).toBeUndefined(); + }); + }); + + describe('processSubscriptionData', () => { + let subscriptionManager: Web3SubscriptionManager; + beforeEach(() => { + subscriptionManager = new Web3SubscriptionManager(requestManager, subscriptions); + sub = new ExampleSubscription({ param1: 'value' }, { subscriptionManager }); + sub['_id'] = 'sub-id'; + }); + afterEach(() => { + jest.clearAllMocks(); + }); + it('should call _processSubscriptionResult when data is type JsonRpcNotification', () => { + const responseWithNotification: JsonRpcNotification = { + jsonrpc: '2.0', + params: { + subscription: '', + result: { id: '' }, + }, + method: '', + }; + jest.spyOn(sub, '_processSubscriptionResult').mockReturnValue(); + sub.processSubscriptionData(responseWithNotification); + expect(sub._processSubscriptionResult).toHaveBeenCalled(); + }); + }); + + describe('buildSubscriptionParams', () => { + let subscriptionManager: Web3SubscriptionManager; + let buildSub: BuildSubscription; + beforeEach(() => { + buildSub = new BuildSubscription({ param1: 'value' }, { subscriptionManager }); + }); + + it('should _buildSubscriptionParams', () => { + expect(() => { + buildSub.buildSubscriptionParams(); + }).toThrow(); + }); + }); }); diff --git a/packages/web3-core/test/unit/web3_subscription_manager.test.ts b/packages/web3-core/test/unit/web3_subscription_manager.test.ts index 403719b292a..fc671b35a7a 100644 --- a/packages/web3-core/test/unit/web3_subscription_manager.test.ts +++ b/packages/web3-core/test/unit/web3_subscription_manager.test.ts @@ -71,7 +71,6 @@ describe('Web3SubscriptionManager', () => { expect.any(Function), ); }); - it('should register the subscription types', () => { subManager = new Web3SubscriptionManager(requestManager, { example: ExampleSubscription as never, @@ -150,6 +149,12 @@ describe('Web3SubscriptionManager', () => { 'Subscription with id "123" already exists', ); }); + it('should error when there is no sub id', async () => { + (sub as any).id = undefined; + // const subManagers = new Web3SubscriptionManager(requestManager, subscriptions) as any + // // eslint-disable-next-line @typescript-eslint/no-unsafe-call + await expect(subManager.addSubscription(sub)).rejects.toThrow(); + }); it('should try to subscribe the subscription', async () => { sub = new ExampleSubscription( @@ -206,7 +211,18 @@ describe('Web3SubscriptionManager', () => { ); }); - it('should try to unsubscribe the subscription', async () => { + it('should unsubscribe to the subscription by id', async () => { + await subManager.unsubscribe(({ id }) => { + if (id === '123') { + return true; + } + return false; + }); + + expect(subManager.subscriptions).toEqual(new Map()); + }); + + it('should unsubscribe in the subscription under the condition', async () => { await subManager.removeSubscription(sub); expect(sub.sendUnsubscribeRequest).toHaveBeenCalledTimes(1); @@ -221,4 +237,28 @@ describe('Web3SubscriptionManager', () => { expect(subManager.subscriptions).toEqual(new Map()); }); }); + describe('messageListener', () => { + let subscription: ExampleSubscription; + + beforeEach(() => { + subManager = new Web3SubscriptionManager(requestManager, subscriptions); + jest.spyOn(subManager, 'supportsSubscriptions').mockReturnValue(true); + subscription = new ExampleSubscription( + { param1: 'param1' }, + { subscriptionManager: subManager }, + ); + (subscription as any).id = '123'; + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + it('should error when no data is provided', () => { + const subManagers = new Web3SubscriptionManager(requestManager, subscriptions) as any; + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + subManagers.messageListener(); + }).toThrow(); + }); + }); }); diff --git a/packages/web3-types/src/json_rpc_types.ts b/packages/web3-types/src/json_rpc_types.ts index a361d018700..9cb98648dc8 100644 --- a/packages/web3-types/src/json_rpc_types.ts +++ b/packages/web3-types/src/json_rpc_types.ts @@ -55,8 +55,9 @@ export interface JsonRpcNotification { readonly jsonrpc: JsonRpcIdentifier; readonly method: string; // for subscription readonly params: SubscriptionParams; // for subscription results - readonly result: never; + readonly result?: never; readonly data?: never; + readonly error?: never; } export interface JsonRpcSubscriptionResult { @@ -91,4 +92,5 @@ export type JsonRpcBatchResponse export type JsonRpcResponse = | JsonRpcResponseWithError | JsonRpcResponseWithResult - | JsonRpcBatchResponse; + | JsonRpcBatchResponse + | JsonRpcNotification; From 968bac929cd6f3926f0689710bbcc1d266d02970 Mon Sep 17 00:00:00 2001 From: Name Date: Tue, 11 Jun 2024 13:14:29 -0400 Subject: [PATCH 23/25] version bump and changelog updates --- CHANGELOG.md | 39 +++++++- packages/web3-core/CHANGELOG.md | 6 +- packages/web3-core/package.json | 4 +- packages/web3-eth-ens/CHANGELOG.md | 6 +- packages/web3-eth-ens/package.json | 8 +- packages/web3-eth/CHANGELOG.md | 6 +- packages/web3-eth/package.json | 6 +- packages/web3-rpc-providers/CHANGELOG.md | 6 ++ packages/web3-rpc-providers/package.json | 6 +- packages/web3-types/CHANGELOG.md | 9 ++ packages/web3-types/package.json | 2 +- packages/web3/CHANGELOG.md | 111 ++++++++++++++++++++++- packages/web3/package.json | 14 +-- packages/web3/src/version.ts | 2 +- tools/web3-plugin-example/CHANGELOG.md | 6 +- tools/web3-plugin-example/package.json | 18 ++-- 16 files changed, 207 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b756bba2604..093b30df294 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2526,4 +2526,41 @@ If there are any bugs, improvements, optimizations or any new feature proposal f - Change `estimateGas` method to add possibility pass Transaction type (#7000) -## [Unreleased] \ No newline at end of file +## [4.10.0] + +### Added + +#### web3 + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +#### web3-core + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +#### web3-eth + +- `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) +- WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) + +#### web3-eth-ens + +- `getText` now supports first param Address +- `getName` has optional second param checkInterfaceSupport + +### web3-types + +- Added `result` as optional `never` and `error` as optional `never in type `JsonRpcNotification` (#7091) +- Added `JsonRpcNotfication` as a union type in `JsonRpcResponse` (#7091) + +### web3-rpc-providers + +- Alpha release + +### Fixed + +#### web3-eth-ens + +- `getName` reverse resolution + +## [Unreleased] diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 6c8e6a2a7e2..67ef64ece5b 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -221,8 +221,10 @@ Documentation: - Set a try catch block if processesingError fails (#7022) -## [Unreleased] +## [4.5.0] ### Added -- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-core/package.json b/packages/web3-core/package.json index 865aafd0db6..a619cfbbc1c 100644 --- a/packages/web3-core/package.json +++ b/packages/web3-core/package.json @@ -1,6 +1,6 @@ { "name": "web3-core", - "version": "4.4.0", + "version": "4.5.0", "description": "Web3 core tools for sub-packages. This is an internal package.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -47,7 +47,7 @@ "web3-eth-iban": "^4.0.7", "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-types": "^1.6.0", + "web3-types": "^1.7.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" }, diff --git a/packages/web3-eth-ens/CHANGELOG.md b/packages/web3-eth-ens/CHANGELOG.md index e5dea285207..2eb11d79a13 100644 --- a/packages/web3-eth-ens/CHANGELOG.md +++ b/packages/web3-eth-ens/CHANGELOG.md @@ -159,7 +159,7 @@ Documentation: - `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) -## [Unreleased] +## [4.4.0] ### Added @@ -168,4 +168,6 @@ Documentation: ### Fixed -- `getName` reverse resolution \ No newline at end of file +- `getName` reverse resolution + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth-ens/package.json b/packages/web3-eth-ens/package.json index 4c1865ca983..e18474e0140 100644 --- a/packages/web3-eth-ens/package.json +++ b/packages/web3-eth-ens/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth-ens", - "version": "4.3.0", + "version": "4.4.0", "description": "This package has ENS functions for interacting with Ethereum Name Service.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -59,12 +59,12 @@ }, "dependencies": { "@adraffy/ens-normalize": "^1.8.8", - "web3-core": "^4.4.0", + "web3-core": "^4.5.0", "web3-errors": "^1.2.0", - "web3-eth": "^4.7.0", + "web3-eth": "^4.8.0", "web3-eth-contract": "^4.5.0", "web3-net": "^4.1.0", - "web3-types": "^1.6.0", + "web3-types": "^1.7.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" } diff --git a/packages/web3-eth/CHANGELOG.md b/packages/web3-eth/CHANGELOG.md index 98dfb42b220..2b6c0e08005 100644 --- a/packages/web3-eth/CHANGELOG.md +++ b/packages/web3-eth/CHANGELOG.md @@ -248,10 +248,12 @@ Documentation: - Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) -## [Unreleased] +## [4.8.0] ### Added - `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) - WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) -- `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) \ No newline at end of file +- `TransactionMiddleware` and `TransactionMiddleware` data types are exported (#7088) + +## [Unreleased] \ No newline at end of file diff --git a/packages/web3-eth/package.json b/packages/web3-eth/package.json index 47c188743b2..336ed74df1e 100644 --- a/packages/web3-eth/package.json +++ b/packages/web3-eth/package.json @@ -1,6 +1,6 @@ { "name": "web3-eth", - "version": "4.7.0", + "version": "4.8.0", "description": "Web3 module to interact with the Ethereum blockchain and smart contracts.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -63,14 +63,14 @@ }, "dependencies": { "setimmediate": "^1.0.5", - "web3-core": "^4.4.0", + "web3-core": "^4.5.0", "web3-errors": "^1.2.0", "web3-eth-abi": "^4.2.2", "web3-eth-accounts": "^4.1.2", "web3-net": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.6.0", + "web3-types": "^1.7.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" } diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index 87f56484e8e..bcf5829d507 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -35,4 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> +## [0.1.0-alpha.1] + +#### Added + +- Alpha release + ## [Unreleased] diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index a3046999279..44e88e4d507 100644 --- a/packages/web3-rpc-providers/package.json +++ b/packages/web3-rpc-providers/package.json @@ -1,6 +1,6 @@ { "name": "web3-rpc-providers", - "version": "0.1.0", + "version": "1.0.0-alpha.0", "description": "Web3 Providers package", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -58,7 +58,7 @@ "dependencies": { "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", - "web3-types": "^1.6.0", - "web3-utils": "^4.2.3" + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0" } } diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 638d9616377..9fba5349a3c 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -195,3 +195,12 @@ Documentation: - Added `signature` to type `AbiFunctionFragment` (#6922) - update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) + +## [1.7.0] + +### Added + +- Added `result` as optional `never` and `error` as optional `never in type `JsonRpcNotification` (#7091) +- Added `JsonRpcNotfication` as a union type in `JsonRpcResponse` (#7091) + +## [Unreleased] diff --git a/packages/web3-types/package.json b/packages/web3-types/package.json index 8cec2cee0b0..b2e7d7b3ff7 100644 --- a/packages/web3-types/package.json +++ b/packages/web3-types/package.json @@ -1,6 +1,6 @@ { "name": "web3-types", - "version": "1.6.0", + "version": "1.7.0", "description": "Provide the common data structures and interfaces for web3 modules.", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index c66601be9ed..0f4e7b32ceb 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -266,12 +266,119 @@ Documentation: ### Added +#### web3 + - Updated type `Web3EthInterface.accounts` to includes `privateKeyToAccount`,`privateKeyToAddress`,and `privateKeyToPublicKey` (#6762) -## [Unreleased] +#### web3-core + +- `defaultReturnFormat` was added to the configuration options. (#6947) + +#### web3-errors + +- Added `InvalidIntegerError` error for fromWei and toWei (#7052) + +#### web3-eth + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) +- `getTransactionFromOrToAttr`, `waitForTransactionReceipt`, `trySendTransaction`, `SendTxHelper` was exported (#7000) + +#### web3-eth-contract + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +#### web3-eth-ens + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +#### web3-net + +- `defaultReturnFormat` was added to all methods that have `ReturnType` param. (#6947) + +#### web3-types + +- Added `signature` to type `AbiFunctionFragment` (#6922) +- update type `Withdrawals`, `block` and `BlockHeaderOutput` to include properties of eip 4844, 4895, 4788 (#6933) + +#### web3-utils + +- `toWei` add warning when using large numbers or large decimals that may cause precision loss (#6908) +- `toWei` and `fromWei` now supports integers as a unit. (#7053) + +### Fixed + +#### web3-eth + +- Fixed issue with simple transactions, Within `checkRevertBeforeSending` if there is no data set in transaction, set gas to be `21000` (#7043) + +#### web3-utils + +- `toWei` support numbers in scientific notation (#6908) +- `toWei` and `fromWei` trims according to ether unit successfuly (#7044) + +#### web3-validator + +- The JSON schema conversion process now correctly assigns an id when the `abi.name` is not available, for example, in the case of public mappings. (#6981) +- `browser` entry point that was pointing to an non-existing bundle file was removed from `package.json` (#7015) + +#### web3-core + +- Set a try catch block if processesingError fails (#7022) + +### Changed + +#### web3-core + +- Interface `RequestManagerMiddleware` was changed (#7003) + +#### web3-eth + +- Added parameter `customTransactionReceiptSchema` into methods `emitConfirmation`, `waitForTransactionReceipt`, `watchTransactionByPolling`, `watchTransactionBySubscription`, `watchTransactionForConfirmations` (#7000) +- Changed functionality: For networks that returns `baseFeePerGas===0x0` fill `maxPriorityFeePerGas` and `maxFeePerGas` by `getGasPrice` method (#7050) + +#### web3-eth-abi + +- Dependencies updated + +#### web3-rpc-methods + +- Change `estimateGas` method to add possibility pass Transaction type (#7000) + +## [4.10.0] ### Added #### web3 -- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) \ No newline at end of file +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +#### web3-core + +- Now when existing packages are added in web3, will be avalible for plugins via context. (#7088) + +#### web3-eth + +- `sendTransaction` in `rpc_method_wrappers` accepts optional param of `TransactionMiddleware` (#7088) +- WebEth has `setTransactionMiddleware` and `getTransactionMiddleware` for automatically passing to `sentTransaction` (#7088) + +#### web3-eth-ens + +- `getText` now supports first param Address +- `getName` has optional second param checkInterfaceSupport + +### web3-types + +- Added `result` as optional `never` and `error` as optional `never in type `JsonRpcNotification` (#7091) +- Added `JsonRpcNotfication` as a union type in `JsonRpcResponse` (#7091) + +### web3-rpc-providers + +- Alpha release + +### Fixed + +#### web3-eth-ens + +- `getName` reverse resolution + +## [Unreleased] diff --git a/packages/web3/package.json b/packages/web3/package.json index 7627ff6826b..13d4d47c242 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -1,6 +1,6 @@ { "name": "web3", - "version": "4.9.0", + "version": "4.10.0", "description": "Ethereum JavaScript API", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", @@ -86,22 +86,22 @@ "web3-providers-ipc": "^4.0.7" }, "dependencies": { - "web3-core": "^4.4.0", + "web3-core": "^4.5.0", "web3-errors": "^1.2.0", - "web3-eth": "^4.7.0", + "web3-eth": "^4.8.0", "web3-eth-abi": "^4.2.2", "web3-eth-accounts": "^4.1.2", "web3-eth-contract": "^4.5.0", - "web3-eth-ens": "^4.3.0", + "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", "web3-eth-personal": "^4.0.8", "web3-net": "^4.1.0", "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.6.0", + "web3-rpc-providers": "^1.0.0-alpha.0", + "web3-types": "^1.7.0", "web3-utils": "^4.3.0", - "web3-validator": "^2.0.6", - "web3-rpc-providers": "^0.1.0" + "web3-validator": "^2.0.6" } } diff --git a/packages/web3/src/version.ts b/packages/web3/src/version.ts index 4ab9622dba7..8b07e0d3591 100644 --- a/packages/web3/src/version.ts +++ b/packages/web3/src/version.ts @@ -1 +1 @@ -/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.9.0' }; +/* eslint-disable header/header */ export const Web3PkgInfo = { version: '4.10.0' }; diff --git a/tools/web3-plugin-example/CHANGELOG.md b/tools/web3-plugin-example/CHANGELOG.md index 636ba482bed..6762e7f8b1b 100644 --- a/tools/web3-plugin-example/CHANGELOG.md +++ b/tools/web3-plugin-example/CHANGELOG.md @@ -88,8 +88,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Dependencies updated -## [Unreleased] - ### Added -Transaction middleware (#7088) \ No newline at end of file +Transaction middleware (#7088) + +## [Unreleased] \ No newline at end of file diff --git a/tools/web3-plugin-example/package.json b/tools/web3-plugin-example/package.json index 2e85b5750ce..c2463255ac8 100644 --- a/tools/web3-plugin-example/package.json +++ b/tools/web3-plugin-example/package.json @@ -1,6 +1,6 @@ { "name": "web3-plugin-example", - "version": "1.0.6", + "version": "1.1.0", "description": "Example implementations of Web3.js' 4.x plugin system", "repository": "https://github.com/ChainSafe/web3.js", "engines": { @@ -45,19 +45,19 @@ "prettier": "^2.7.1", "ts-jest": "^29.1.1", "typescript": "^4.7.4", - "web3": "^4.3.0", - "web3-core": "^4.3.2", - "web3-eth-abi": "^4.1.4", - "web3-eth-contract": "^4.1.4", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.0" + "web3": "^4.10.0", + "web3-core": "^4.5.0", + "web3-eth-abi": "^4.2.2", + "web3-eth-contract": "^4.5.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0" }, "peerDependencies": { "web3-core": ">= 4.1.1 < 5", + "web3-eth": ">= 4.7.0 < 5", "web3-eth-abi": ">= 4.1.1 < 5", "web3-eth-contract": ">= 4.0.5 < 5", "web3-types": ">= 1.1.1 < 5", - "web3-utils": ">= 4.0.5 < 5", - "web3-eth": ">= 4.7.0 < 5" + "web3-utils": ">= 4.0.5 < 5" } } From 27c790fcbd0937bf71376c32d1f594ed4208efdf Mon Sep 17 00:00:00 2001 From: Alex Luu Date: Wed, 12 Jun 2024 15:53:00 -0400 Subject: [PATCH 24/25] change rpc-providers version to rc --- packages/web3-rpc-providers/CHANGELOG.md | 4 ++-- packages/web3-rpc-providers/package.json | 2 +- packages/web3/CHANGELOG.md | 2 +- packages/web3/package.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/web3-rpc-providers/CHANGELOG.md b/packages/web3-rpc-providers/CHANGELOG.md index bcf5829d507..1909cc7a509 100644 --- a/packages/web3-rpc-providers/CHANGELOG.md +++ b/packages/web3-rpc-providers/CHANGELOG.md @@ -35,10 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --> -## [0.1.0-alpha.1] +## [1.0.0.rc.0] #### Added -- Alpha release +- RC release ## [Unreleased] diff --git a/packages/web3-rpc-providers/package.json b/packages/web3-rpc-providers/package.json index 44e88e4d507..6904037773a 100644 --- a/packages/web3-rpc-providers/package.json +++ b/packages/web3-rpc-providers/package.json @@ -1,6 +1,6 @@ { "name": "web3-rpc-providers", - "version": "1.0.0-alpha.0", + "version": "1.0.0-rc.0", "description": "Web3 Providers package", "main": "./lib/commonjs/index.js", "module": "./lib/esm/index.js", diff --git a/packages/web3/CHANGELOG.md b/packages/web3/CHANGELOG.md index 0f4e7b32ceb..2e649c3ee0f 100644 --- a/packages/web3/CHANGELOG.md +++ b/packages/web3/CHANGELOG.md @@ -373,7 +373,7 @@ Documentation: ### web3-rpc-providers -- Alpha release +- RC release ### Fixed diff --git a/packages/web3/package.json b/packages/web3/package.json index 13d4d47c242..5d05fa85923 100644 --- a/packages/web3/package.json +++ b/packages/web3/package.json @@ -99,7 +99,7 @@ "web3-providers-http": "^4.1.0", "web3-providers-ws": "^4.0.7", "web3-rpc-methods": "^1.3.0", - "web3-rpc-providers": "^1.0.0-alpha.0", + "web3-rpc-providers": "^1.0.0-rc.0", "web3-types": "^1.7.0", "web3-utils": "^4.3.0", "web3-validator": "^2.0.6" From d6d4c6df8f6b6323bc5fe277cbee969c28c845a7 Mon Sep 17 00:00:00 2001 From: Alex Luu Date: Wed, 12 Jun 2024 15:55:49 -0400 Subject: [PATCH 25/25] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 093b30df294..783691404b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2555,7 +2555,7 @@ If there are any bugs, improvements, optimizations or any new feature proposal f ### web3-rpc-providers -- Alpha release +- RC release ### Fixed