diff --git a/package.json b/package.json
index 9a649184..dda2a017 100644
--- a/package.json
+++ b/package.json
@@ -32,14 +32,16 @@
"@emotion/styled": "^11.10.5",
"@mdi/js": "^7.0.96",
"@mdi/react": "^1.6.1",
- "@reduxjs/toolkit": "^1.8.1",
- "@testing-library/dom": "^8.19.0",
"@mui/icons-material": "^5.15.11",
"@mui/material": "^5.15.11",
"@mui/system": "^5.15.11",
+ "@reduxjs/toolkit": "^1.8.1",
+ "@testing-library/dom": "^8.19.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.0.1",
"@testing-library/user-event": "^14.1.1",
+ "@types/big.js": "^6.2.2",
+ "@types/ethereum-protocol": "^1.0.5",
"@types/jest": "^27.4.1",
"@types/lodash": "^4.14.189",
"@types/node": "^17.0.25",
@@ -61,6 +63,7 @@
"formik": "^2.2.9",
"framer-motion": "^8.4.3",
"html-webpack-plugin": "^5.3.2",
+ "json-loader": "^0.5.7",
"lodash": "^4.17.21",
"path": "^0.12.7",
"postcss": "^8.2.1",
@@ -79,9 +82,11 @@
"webpack-cli": "^5.0.0",
"webpack-dev-server": "^4.3.1",
"webpack-merge": "^5.8.0",
- "yup": "^0.32.11"
+ "yup": "^0.32.11",
+ "ethers": "^6.13.2"
},
"dependencies": {
+ "big.js": "^6.2.1",
"react": "^18.2.0",
"react-circle-flags": "^0.0.18",
"react-dom": "^18.2.0"
diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx
new file mode 100644
index 00000000..c2f315dc
--- /dev/null
+++ b/src/components/Alert.tsx
@@ -0,0 +1,71 @@
+import { Box, Typography } from '@mui/material'
+import React from 'react'
+
+const Alert = ({
+ variant,
+ title,
+ content,
+}: {
+ variant: 'info' | 'negative'
+ title?: string
+ content: string
+}) => {
+ return (
+
+
+ {variant === 'info' && (
+
+ )}
+ {variant === 'negative' && (
+
+ )}
+
+
+ {title && (
+
+ {title}
+
+ )}
+ {content && {content}}
+
+
+ )
+}
+
+export default Alert
diff --git a/src/components/CamInput.tsx b/src/components/CamInput.tsx
new file mode 100644
index 00000000..2f2363a9
--- /dev/null
+++ b/src/components/CamInput.tsx
@@ -0,0 +1,137 @@
+import Big from 'big.js'
+import BN from 'bn.js'
+import React, { useCallback, useEffect, useState } from 'react'
+
+Big.PE = 32
+
+function bnToBig(val, denomination) {
+ return new Big(val.toString()).div(Math.pow(10, denomination))
+}
+
+function bigToBN(val, denomination) {
+ return new BN(val.mul(Math.pow(10, denomination)).toString())
+}
+
+const DecimalInput = ({
+ denomination = 0,
+ max = null,
+ min = 0,
+ step = null,
+ placeholder,
+ value,
+ initial = null,
+ onChange,
+}) => {
+ const [val, setVal] = useState(bnToString(initial))
+
+ const bnToString = useCallback(
+ val => {
+ return val ? bnToBig(val, denomination).toString() : null
+ },
+ [denomination],
+ )
+
+ const stringToBN = useCallback(
+ strVal => {
+ return bigToBN(new Big(strVal), denomination)
+ },
+ [denomination],
+ )
+
+ const maxNumBN = max
+ const maxNumString = bnToString(maxNumBN)
+
+ const stepNum = (() => {
+ if (!step) {
+ if (denomination >= 2) {
+ return 0.01
+ } else {
+ return Math.pow(10, -denomination)
+ }
+ }
+ try {
+ return bnToString(step)
+ } catch (e) {
+ console.error(e)
+ return '0.01'
+ }
+ })()
+
+ useEffect(() => {
+ if (!val) {
+ onChange(new BN(0))
+ return
+ }
+ try {
+ let splitVal = val.toString().split('.')
+ let wholeVal = splitVal[0]
+ let denomVal = splitVal[1]
+ if (denomVal) {
+ if (denomVal.length > denomination) {
+ let newDenom = denomVal.substring(0, denomination)
+ setVal(`${wholeVal}.${newDenom}`)
+ return
+ }
+ }
+ } catch (e) {
+ console.log(e)
+ }
+ if (parseFloat(val) < min) {
+ setVal(min.toString())
+ return
+ }
+ let valBn = stringToBN(val)
+ onChange(valBn)
+ }, [val, denomination, min, onChange, stringToBN])
+
+ useEffect(() => {
+ setVal(bnToString(value))
+ }, [value, bnToString])
+
+ const handleChange = e => {
+ setVal(e.target.value)
+ }
+
+ const handleBlur = () => {
+ // If number is above max amount, correct it
+ const valBig = Big(val || '0')
+ const valBN = bigToBN(valBig, denomination)
+ if (maxNumBN != null) {
+ if (valBN.gt(maxNumBN)) {
+ setVal(bnToString(maxNumBN))
+ }
+ }
+ }
+
+ const maxout = () => {
+ if (maxNumBN != null) {
+ setVal(bnToString(maxNumBN))
+ }
+ }
+
+ const clear = () => {
+ setVal(undefined)
+ }
+
+ return (
+
+ )
+}
+
+export default DecimalInput
diff --git a/src/components/Input.tsx b/src/components/Input.tsx
new file mode 100644
index 00000000..75476493
--- /dev/null
+++ b/src/components/Input.tsx
@@ -0,0 +1,81 @@
+import { InputAdornment, Typography } from '@mui/material'
+import TextField from '@mui/material/TextField' // Import TextField if using Material-UI
+import React, { useMemo } from 'react'
+import { actionTypes, usePartnerConfigurationContext } from '../helpers/partnerConfigurationContext'
+
+const Input = ({ variant = 'outlined', ...rest }) => {
+ const { state, dispatch } = usePartnerConfigurationContext()
+ const error = useMemo(() => {
+ if (!state.balance) return true
+ let balance = parseFloat(state.balance)
+ if (balance < 100) return true
+ else return false
+ }, [state])
+ return (
+ {
+ dispatch({
+ type: actionTypes.UPDATE_BALANCE,
+ payload: {
+ newValue: e.target.value,
+ },
+ })
+ }}
+ type="number"
+ error={error}
+ InputProps={{
+ sx: {
+ '& input': {
+ fontSize: '16px',
+ },
+ },
+ startAdornment: (
+ theme.palette.text.primary,
+ }}
+ >
+ Prefund Amount:
+
+ ),
+ endAdornment: error ? (
+
+
+
+ ) : (
+
+
+
+ ),
+ }}
+ {...rest}
+ />
+ )
+}
+
+export default Input
diff --git a/src/components/MainButton.tsx b/src/components/MainButton.tsx
index a0070302..1f29b5f5 100644
--- a/src/components/MainButton.tsx
+++ b/src/components/MainButton.tsx
@@ -1,30 +1,40 @@
+import { Button, CircularProgress, SvgIconTypeMap, Typography } from '@mui/material'
+import { OverridableComponent } from '@mui/material/OverridableComponent'
import * as React from 'react'
-import { Button } from '@mui/material'
function MainButton({
variant,
onClick,
children,
style,
+ disabled,
+ loading,
+ endIcon,
}: {
variant: 'contained' | 'outlined'
onClick?: React.MouseEventHandler
children: React.ReactNode
style?: React.CSSProperties
+ disabled?: boolean
+ loading?: boolean
+ endIcon?: any
}) {
return (
)
}
diff --git a/src/helpers/CMAccountManagerModule#CMAccount.json b/src/helpers/CMAccountManagerModule#CMAccount.json
new file mode 100644
index 00000000..15f3682f
--- /dev/null
+++ b/src/helpers/CMAccountManagerModule#CMAccount.json
@@ -0,0 +1,2396 @@
+[
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [],
+ "name": "AccessControlBadConfirmation",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "neededRole",
+ "type": "bytes32"
+ }
+ ],
+ "name": "AccessControlUnauthorizedAccount",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ }
+ ],
+ "name": "AddressEmptyCode",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "AddressInsufficientBalance",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "latestImplementation",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "newImplementation",
+ "type": "address"
+ }
+ ],
+ "name": "CMAccountImplementationMismatch",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "oldImplementation",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "newImplementation",
+ "type": "address"
+ }
+ ],
+ "name": "CMAccountNoUpgradeNeeded",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "expiresAt",
+ "type": "uint256"
+ }
+ ],
+ "name": "ChequeExpired",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "DepositorNotAllowed",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "ECDSAInvalidSignature",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "length",
+ "type": "uint256"
+ }
+ ],
+ "name": "ECDSAInvalidSignatureLength",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "ECDSAInvalidSignatureS",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "implementation",
+ "type": "address"
+ }
+ ],
+ "name": "ERC1967InvalidImplementation",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "ERC1967NonPayable",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "FailedInnerCall",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "chequeAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "InvalidAmount",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "chequeCounter",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastCounter",
+ "type": "uint256"
+ }
+ ],
+ "name": "InvalidCounter",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "fromCMAccount",
+ "type": "address"
+ }
+ ],
+ "name": "InvalidFromCMAccount",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "InvalidInitialization",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint8",
+ "name": "use",
+ "type": "uint8"
+ }
+ ],
+ "name": "InvalidPublicKeyUseType",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "toCMAccount",
+ "type": "address"
+ }
+ ],
+ "name": "InvalidToCMAccount",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "signer",
+ "type": "address"
+ }
+ ],
+ "name": "NotAllowedToSignCheques",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "NotInitializing",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ }
+ ],
+ "name": "PaymentTokenAlreadyExists",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ }
+ ],
+ "name": "PaymentTokenDoesNotExist",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "withdrawableAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefundLeft",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "PrefundNotSpentYet",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "pubKeyAddress",
+ "type": "address"
+ }
+ ],
+ "name": "PublicKeyAlreadyExists",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "pubKeyAddress",
+ "type": "address"
+ }
+ ],
+ "name": "PublicKeyDoesNotExist",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "ReentrancyGuardReentrantCall",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ }
+ ],
+ "name": "SafeERC20FailedOperation",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "ServiceAlreadyExists",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "ServiceDoesNotExist",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "TransferToZeroAddress",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "UUPSUnauthorizedCallContext",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "slot",
+ "type": "bytes32"
+ }
+ ],
+ "name": "UUPSUnsupportedProxiableUUID",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "WantedServiceAlreadyExists",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "WantedServiceDoesNotExist",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "limit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "WithdrawalLimitExceeded",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "limit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "WithdrawalLimitExceededForPeriod",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "ZeroValueDeposit",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "oldImplementation",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newImplementation",
+ "type": "address"
+ }
+ ],
+ "name": "CMAccountUpgraded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "fromBot",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "toBot",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "counter",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "paid",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "developerFee",
+ "type": "uint256"
+ }
+ ],
+ "name": "ChequeCashedIn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "fromCMAccount",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "toCMAccount",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "fromBot",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "toBot",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "counter",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "payment",
+ "type": "uint256"
+ }
+ ],
+ "name": "ChequeVerified",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposit",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "withdrawer",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "GasMoneyWithdrawal",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "limit",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "period",
+ "type": "uint256"
+ }
+ ],
+ "name": "GasMoneyWithdrawalUpdated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint64",
+ "name": "version",
+ "type": "uint64"
+ }
+ ],
+ "name": "Initialized",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "bot",
+ "type": "address"
+ }
+ ],
+ "name": "MessengerBotAdded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "bot",
+ "type": "address"
+ }
+ ],
+ "name": "MessengerBotRemoved",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "supportsOffChainPayment",
+ "type": "bool"
+ }
+ ],
+ "name": "OffChainPaymentSupportUpdated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ }
+ ],
+ "name": "PaymentTokenAdded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ }
+ ],
+ "name": "PaymentTokenRemoved",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "pubKeyAddress",
+ "type": "address"
+ }
+ ],
+ "name": "PublicKeyAdded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "pubKeyAddress",
+ "type": "address"
+ }
+ ],
+ "name": "PublicKeyRemoved",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "previousAdminRole",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "newAdminRole",
+ "type": "bytes32"
+ }
+ ],
+ "name": "RoleAdminChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "RoleGranted",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "RoleRevoked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "ServiceAdded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "ServiceCapabilitiesUpdated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "capability",
+ "type": "string"
+ }
+ ],
+ "name": "ServiceCapabilityAdded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "capability",
+ "type": "string"
+ }
+ ],
+ "name": "ServiceCapabilityRemoved",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "fee",
+ "type": "uint256"
+ }
+ ],
+ "name": "ServiceFeeUpdated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "ServiceRemoved",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "restrictedRate",
+ "type": "bool"
+ }
+ ],
+ "name": "ServiceRestrictedRateUpdated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "implementation",
+ "type": "address"
+ }
+ ],
+ "name": "Upgraded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "WantedServiceAdded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "WantedServiceRemoved",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "receiver",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdraw",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "BOOKING_OPERATOR_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "BOT_ADMIN_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "CHEQUE_OPERATOR_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "DEFAULT_ADMIN_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "DOMAIN_TYPEHASH",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "GAS_WITHDRAWER_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "MESSENGER_CHEQUE_TYPEHASH",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "SERVICE_ADMIN_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "UPGRADER_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "UPGRADE_INTERFACE_VERSION",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "WITHDRAWER_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "bot",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "gasMoney",
+ "type": "uint256"
+ }
+ ],
+ "name": "addMessengerBot",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "pubKeyAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "addPublicKey",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "fee",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "restrictedRate",
+ "type": "bool"
+ },
+ {
+ "internalType": "string[]",
+ "name": "capabilities",
+ "type": "string[]"
+ }
+ ],
+ "name": "addService",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "capability",
+ "type": "string"
+ }
+ ],
+ "name": "addServiceCapability",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_supportedToken",
+ "type": "address"
+ }
+ ],
+ "name": "addSupportedToken",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string[]",
+ "name": "serviceNames",
+ "type": "string[]"
+ }
+ ],
+ "name": "addWantedServices",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "buyBookingToken",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "fromCMAccount",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "toCMAccount",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "toBot",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "counter",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "createdAt",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "expiresAt",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "name": "cashInCheque",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getAllServiceHashes",
+ "outputs": [
+ {
+ "internalType": "bytes32[]",
+ "name": "serviceHashes",
+ "type": "bytes32[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getBookingTokenAddress",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getDomainSeparator",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getGasMoneyWithdrawal",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "withdrawalLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawalPeriod",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getGasMoneyWithdrawalForAccount",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "periodStart",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawnAmount",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "fromBot",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "toBot",
+ "type": "address"
+ }
+ ],
+ "name": "getLastCashIn",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "lastCounter",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastCreatedAt",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "lastExpiresAt",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getManagerAddress",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getPrefundAmount",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "pubKeyAddress",
+ "type": "address"
+ }
+ ],
+ "name": "getPublicKey",
+ "outputs": [
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getPublicKeysAddresses",
+ "outputs": [
+ {
+ "internalType": "address[]",
+ "name": "pubKeyAddresses",
+ "type": "address[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getRoleAdmin",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "index",
+ "type": "uint256"
+ }
+ ],
+ "name": "getRoleMember",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getRoleMemberCount",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getService",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "_fee",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "_restrictedRate",
+ "type": "bool"
+ },
+ {
+ "internalType": "string[]",
+ "name": "_capabilities",
+ "type": "string[]"
+ }
+ ],
+ "internalType": "struct PartnerConfiguration.Service",
+ "name": "service",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ }
+ ],
+ "name": "getServiceCapabilities",
+ "outputs": [
+ {
+ "internalType": "string[]",
+ "name": "capabilities",
+ "type": "string[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getServiceCapabilities",
+ "outputs": [
+ {
+ "internalType": "string[]",
+ "name": "capabilities",
+ "type": "string[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ }
+ ],
+ "name": "getServiceFee",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "fee",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getServiceFee",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "fee",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getServiceRestrictedRate",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "restrictedRate",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ }
+ ],
+ "name": "getServiceRestrictedRate",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "restrictedRate",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getSupportedServices",
+ "outputs": [
+ {
+ "internalType": "string[]",
+ "name": "serviceNames",
+ "type": "string[]"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "_fee",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "_restrictedRate",
+ "type": "bool"
+ },
+ {
+ "internalType": "string[]",
+ "name": "_capabilities",
+ "type": "string[]"
+ }
+ ],
+ "internalType": "struct PartnerConfiguration.Service[]",
+ "name": "services",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getSupportedTokens",
+ "outputs": [
+ {
+ "internalType": "address[]",
+ "name": "tokens",
+ "type": "address[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getTotalChequePayments",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getWantedServiceHashes",
+ "outputs": [
+ {
+ "internalType": "bytes32[]",
+ "name": "serviceHashes",
+ "type": "bytes32[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getWantedServices",
+ "outputs": [
+ {
+ "internalType": "string[]",
+ "name": "serviceNames",
+ "type": "string[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "grantRole",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "hasRole",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "fromCMAccount",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "toCMAccount",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "toBot",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "counter",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "createdAt",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "expiresAt",
+ "type": "uint256"
+ }
+ ],
+ "name": "hashMessengerCheque",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "fromCMAccount",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "toCMAccount",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "toBot",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "counter",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "createdAt",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "expiresAt",
+ "type": "uint256"
+ }
+ ],
+ "name": "hashTypedDataV4",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "manager",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "bookingToken",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefundAmount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "defaultAdmin",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "upgrader",
+ "type": "address"
+ }
+ ],
+ "name": "initialize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "bot",
+ "type": "address"
+ }
+ ],
+ "name": "isBotAllowed",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "reservedFor",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "uri",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "expirationTimestamp",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "price",
+ "type": "uint256"
+ },
+ {
+ "internalType": "contract IERC20",
+ "name": "paymentToken",
+ "type": "address"
+ }
+ ],
+ "name": "mintBookingToken",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "offChainPaymentSupported",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "",
+ "type": "bytes"
+ }
+ ],
+ "name": "onERC721Received",
+ "outputs": [
+ {
+ "internalType": "bytes4",
+ "name": "",
+ "type": "bytes4"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "proxiableUUID",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "bot",
+ "type": "address"
+ }
+ ],
+ "name": "removeMessengerBot",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "pubKeyAddress",
+ "type": "address"
+ }
+ ],
+ "name": "removePublicKey",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ }
+ ],
+ "name": "removeService",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "capability",
+ "type": "string"
+ }
+ ],
+ "name": "removeServiceCapability",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_supportedToken",
+ "type": "address"
+ }
+ ],
+ "name": "removeSupportedToken",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string[]",
+ "name": "serviceNames",
+ "type": "string[]"
+ }
+ ],
+ "name": "removeWantedServices",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "callerConfirmation",
+ "type": "address"
+ }
+ ],
+ "name": "renounceRole",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "revokeRole",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "limit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "period",
+ "type": "uint256"
+ }
+ ],
+ "name": "setGasMoneyWithdrawal",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bool",
+ "name": "_isSupported",
+ "type": "bool"
+ }
+ ],
+ "name": "setOffChainPaymentSupported",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ },
+ {
+ "internalType": "string[]",
+ "name": "capabilities",
+ "type": "string[]"
+ }
+ ],
+ "name": "setServiceCapabilities",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ },
+ {
+ "internalType": "uint256",
+ "name": "fee",
+ "type": "uint256"
+ }
+ ],
+ "name": "setServiceFee",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ },
+ {
+ "internalType": "bool",
+ "name": "restrictedRate",
+ "type": "bool"
+ }
+ ],
+ "name": "setServiceRestrictedRate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "interfaceId",
+ "type": "bytes4"
+ }
+ ],
+ "name": "supportsInterface",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "contract IERC20",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferERC20",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "contract IERC721",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferERC721",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newImplementation",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "upgradeToAndCall",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "fromCMAccount",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "toCMAccount",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "toBot",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "counter",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "createdAt",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "expiresAt",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "name": "verifyCheque",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "signer",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "paymentAmount",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdraw",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawGasMoney",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+]
diff --git a/src/helpers/ManagerProxyModule#CMAccountManager.json b/src/helpers/ManagerProxyModule#CMAccountManager.json
new file mode 100644
index 00000000..fc69798c
--- /dev/null
+++ b/src/helpers/ManagerProxyModule#CMAccountManager.json
@@ -0,0 +1,1118 @@
+{
+ "_format": "hh-sol-artifact-1",
+ "contractName": "CMAccountManager",
+ "sourceName": "contracts/manager/CMAccountManager.sol",
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [],
+ "name": "AccessControlBadConfirmation",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "neededRole",
+ "type": "bytes32"
+ }
+ ],
+ "name": "AccessControlUnauthorizedAccount",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ }
+ ],
+ "name": "AddressEmptyCode",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "AddressInsufficientBalance",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "admin",
+ "type": "address"
+ }
+ ],
+ "name": "CMAccountInvalidAdmin",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "implementation",
+ "type": "address"
+ }
+ ],
+ "name": "CMAccountInvalidImplementation",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "implementation",
+ "type": "address"
+ }
+ ],
+ "name": "ERC1967InvalidImplementation",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "ERC1967NonPayable",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "EnforcedPause",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "ExpectedPause",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "FailedInnerCall",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "expected",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "sended",
+ "type": "uint256"
+ }
+ ],
+ "name": "IncorrectPrefundAmount",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "bookingToken",
+ "type": "address"
+ }
+ ],
+ "name": "InvalidBookingTokenAddress",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "developerWallet",
+ "type": "address"
+ }
+ ],
+ "name": "InvalidDeveloperWallet",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "InvalidInitialization",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "NotInitializing",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "ReentrancyGuardReentrantCall",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ }
+ ],
+ "name": "ServiceAlreadyRegistered",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "ServiceNotRegistered",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "UUPSUnauthorizedCallContext",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "slot",
+ "type": "bytes32"
+ }
+ ],
+ "name": "UUPSUnsupportedProxiableUUID",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "oldBookingToken",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newBookingToken",
+ "type": "address"
+ }
+ ],
+ "name": "BookingTokenAddressUpdated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "CMAccountCreated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "oldImplementation",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newImplementation",
+ "type": "address"
+ }
+ ],
+ "name": "CMAccountImplementationUpdated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "oldDeveloperFeeBp",
+ "type": "uint256"
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "newDeveloperFeeBp",
+ "type": "uint256"
+ }
+ ],
+ "name": "DeveloperFeeBpUpdated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "oldDeveloperWallet",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newDeveloperWallet",
+ "type": "address"
+ }
+ ],
+ "name": "DeveloperWalletUpdated",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint64",
+ "name": "version",
+ "type": "uint64"
+ }
+ ],
+ "name": "Initialized",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "Paused",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "previousAdminRole",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "newAdminRole",
+ "type": "bytes32"
+ }
+ ],
+ "name": "RoleAdminChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "RoleGranted",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "RoleRevoked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "ServiceRegistered",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "ServiceUnregistered",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "Unpaused",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "implementation",
+ "type": "address"
+ }
+ ],
+ "name": "Upgraded",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "CMACCOUNT_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "DEFAULT_ADMIN_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "DEVELOPER_WALLET_ADMIN_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "FEE_ADMIN_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "PAUSER_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "PREFUND_ADMIN_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "SERVICE_REGISTRY_ADMIN_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "UPGRADER_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "UPGRADE_INTERFACE_VERSION",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "VERSIONER_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "admin",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "upgrader",
+ "type": "address"
+ }
+ ],
+ "name": "createCMAccount",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getAccountImplementation",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getAllRegisteredServiceHashes",
+ "outputs": [
+ {
+ "internalType": "bytes32[]",
+ "name": "services",
+ "type": "bytes32[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getAllRegisteredServiceNames",
+ "outputs": [
+ {
+ "internalType": "string[]",
+ "name": "services",
+ "type": "string[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getBookingTokenAddress",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getCMAccountCreator",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getDeveloperFeeBp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "developerFeeBp",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getDeveloperWallet",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "developerWallet",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getPrefundAmount",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ }
+ ],
+ "name": "getRegisteredServiceHashByName",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "serviceHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getRegisteredServiceNameByHash",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getRoleAdmin",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "index",
+ "type": "uint256"
+ }
+ ],
+ "name": "getRoleMember",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ }
+ ],
+ "name": "getRoleMemberCount",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "grantRole",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "hasRole",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "defaultAdmin",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "pauser",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "upgrader",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "versioner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "developerWallet",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "developerFeeBp",
+ "type": "uint256"
+ }
+ ],
+ "name": "initialize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "isCMAccount",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "pause",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "paused",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "proxiableUUID",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ }
+ ],
+ "name": "registerService",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "callerConfirmation",
+ "type": "address"
+ }
+ ],
+ "name": "renounceRole",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "role",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "revokeRole",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newImplementation",
+ "type": "address"
+ }
+ ],
+ "name": "setAccountImplementation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ }
+ ],
+ "name": "setBookingTokenAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "bp",
+ "type": "uint256"
+ }
+ ],
+ "name": "setDeveloperFeeBp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "developerWallet",
+ "type": "address"
+ }
+ ],
+ "name": "setDeveloperWallet",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "newPrefundAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "setPrefundAmount",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "interfaceId",
+ "type": "bytes4"
+ }
+ ],
+ "name": "supportsInterface",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unpause",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "string",
+ "name": "serviceName",
+ "type": "string"
+ }
+ ],
+ "name": "unregisterService",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newImplementation",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "upgradeToAndCall",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ }
+ ],
+ "bytecode": "0x60a0604052306080523480156200001557600080fd5b506200002062000026565b620000da565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620000775760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620000d75780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b608051612f7462000104600039600081816115bf015281816115e901526117440152612f746000f3fe608060405260043610620002185760003560e01c806301601d2f146200021d57806301ffc9a714620002555780630470d3ac146200028b57806309766da214620002b25780630d6115d014620002d957806312b357b514620002fe5780631c2b3afc1462000323578063248a9ca314620003485780632cec1a06146200036d5780632f2ff15d1462000392578063352af39a14620003b757806336568abe14620003dc5780633c55593814620004015780633f4ba83a146200041957806340df8d8414620004315780634cba593a14620004565780634f1ef286146200047b5780634f3f4639146200049257806352d1902d14620004aa5780635a81a62614620004c25780635c975abb14620004f65780635e818619146200050e5780636cd5687814620005335780637fa3465714620005585780638127f465146200057d5780638456cb5914620005a45780639010d07c14620005bc57806391d1485414620005e157806392cf833f146200060657806395b6ef0c146200062b5780639d825bc51462000650578063a217fddf1462000668578063ad3cb1cc146200067f578063b289819c14620006b2578063c17e30bf14620006d7578063c2a1db7814620006fc578063c39409e11462000723578063ca15c873146200073b578063d547741f1462000760578063e63ab1e91462000785578063f72c0d8b14620007aa578063f85b4a9c14620007cf578063fd2fbd5214620007f4575b600080fd5b3480156200022a57600080fd5b506200024260008051602062002e1f83398151915281565b6040519081526020015b60405180910390f35b3480156200026257600080fd5b506200027a620002743660046200241c565b6200080b565b60405190151581526020016200024c565b3480156200029857600080fd5b50620002a362000839565b6040516200024c919062002448565b348015620002bf57600080fd5b50620002d7620002d136600462002479565b62000859565b005b348015620002e657600080fd5b50620002d7620002f836600462002529565b6200090b565b3480156200030b57600080fd5b506200027a6200031d36600462002479565b62000935565b3480156200033057600080fd5b50620002d76200034236600462002576565b62000967565b3480156200035557600080fd5b50620002426200036736600462002576565b62000999565b3480156200037a57600080fd5b50620002a36200038c36600462002479565b620009bb565b3480156200039f57600080fd5b50620002d7620003b136600462002590565b620009f3565b348015620003c457600080fd5b5062000242620003d636600462002529565b62000a1b565b348015620003e957600080fd5b50620002d7620003fb36600462002590565b62000aaa565b3480156200040e57600080fd5b506200024262000ae5565b3480156200042657600080fd5b50620002d762000afc565b3480156200043e57600080fd5b506200024260008051602062002eff83398151915281565b3480156200046357600080fd5b506200024260008051602062002e5f83398151915281565b620002d76200048c366004620025bf565b62000b24565b3480156200049f57600080fd5b50620002a362000b45565b348015620004b757600080fd5b506200024262000b65565b348015620004cf57600080fd5b50620004e7620004e136600462002576565b62000b85565b6040516200024c91906200267b565b3480156200050357600080fd5b506200027a62000c68565b3480156200051b57600080fd5b50620002d76200052d36600462002529565b62000c7f565b3480156200054057600080fd5b50620002d76200055236600462002479565b62000ca5565b3480156200056557600080fd5b506200024260008051602062002f1f83398151915281565b3480156200058a57600080fd5b506200059562000d4a565b6040516200024c919062002690565b348015620005b157600080fd5b50620002d762000d6b565b348015620005c957600080fd5b50620002a3620005db366004620026d6565b62000d90565b348015620005ee57600080fd5b506200027a6200060036600462002590565b62000dc2565b3480156200061357600080fd5b506200024260008051602062002e3f83398151915281565b3480156200063857600080fd5b50620002d76200064a366004620026f9565b62000dfa565b3480156200065d57600080fd5b50620002a362000fb8565b3480156200067557600080fd5b5062000242600081565b3480156200068c57600080fd5b50620004e7604051806040016040528060058152602001640352e302e360dc1b81525081565b348015620006bf57600080fd5b506200024260008051602062002e7f83398151915281565b348015620006e457600080fd5b50620002d7620006f636600462002479565b62000fd5565b3480156200070957600080fd5b50620007146200107e565b6040516200024c919062002771565b3480156200073057600080fd5b5062000242620011f3565b3480156200074857600080fd5b50620002426200075a36600462002576565b6200120a565b3480156200076d57600080fd5b50620002d76200077f36600462002590565b6200123a565b3480156200079257600080fd5b506200024260008051602062002edf83398151915281565b348015620007b757600080fd5b506200024260008051602062002e9f83398151915281565b348015620007dc57600080fd5b50620002d7620007ee36600462002576565b6200125c565b620002a362000805366004620027d9565b620012c2565b60006001600160e01b03198216635a05180f60e01b14806200083357506200083382620012f0565b92915050565b6000806200084662001327565b600201546001600160a01b031692915050565b60008051602062002e7f83398151915262000874816200134b565b816001600160a01b03163b600003620008ad57816040516337766f4360e11b8152600401620008a4919062002448565b60405180910390fd5b6000620008b962000fb8565b9050620008c68362001357565b826001600160a01b0316816001600160a01b03167fecd599290ada9c149ae0fb600bc6ada3c103a716eadb877b5341b7d298b62d9360405160405180910390a3505050565b60008051602062002e3f83398151915262000926816200134b565b620009318262001385565b5050565b6000806200094262001327565b6001600160a01b03909316600090815260059093016020525050604090205460ff1690565b60008051602062002e1f83398151915262000982816200134b565b60006200098e62001327565b600101929092555050565b600080620009a662001478565b60009384526020525050604090206001015490565b600080620009c862001327565b6001600160a01b03938416600090815260059091016020526040902054610100900490921692915050565b620009fe8262000999565b62000a09816200134b565b62000a1583836200149c565b50505050565b60008062000a28620014e5565b905062000a618360405160200162000a41919062002808565b60408051601f198184030181529190528051602090910120829062001509565b62000a7f5760405163162e926760e11b815260040160405180910390fd5b806003018360405162000a93919062002808565b908152602001604051809103902054915050919050565b6001600160a01b038116331462000ad45760405163334bd91960e11b815260040160405180910390fd5b62000ae0828262001517565b505050565b60008062000af262001327565b6003015492915050565b60008051602062002edf83398151915262000b17816200134b565b62000b2162001557565b50565b62000b2e620015b4565b62000b39826200165f565b6200093182826200167a565b60008062000b5262001327565b600401546001600160a01b031692915050565b600062000b7162001739565b5060008051602062002ebf83398151915290565b6060600062000b93620014e5565b905062000ba1818462001509565b62000bbf5760405163162e926760e11b815260040160405180910390fd5b60008381526002820160205260409020805462000bdc9062002826565b80601f016020809104026020016040519081016040528092919081815260200182805462000c0a9062002826565b801562000c5b5780601f1062000c2f5761010080835404028352916020019162000c5b565b820191906000526020600020905b81548152906001019060200180831162000c3d57829003601f168201915b5050505050915050919050565b60008062000c7562001783565b5460ff1692915050565b60008051602062002e3f83398151915262000c9a816200134b565b6200093182620017a7565b60008051602062002eff83398151915262000cc0816200134b565b6001600160a01b03821662000cec578160405163220b4f1160e11b8152600401620008a4919062002448565b600062000cf862000839565b905062000d058362001885565b826001600160a01b0316816001600160a01b03167f88bf70d4f3c446213b5064d7cfe95ec0ed196748f014c19a833117bac32468fd60405160405180910390a3505050565b6060600062000d58620014e5565b905062000d6581620018b6565b91505090565b60008051602062002edf83398151915262000d86816200134b565b62000b21620018c5565b60008062000d9d62001911565b600085815260208290526040902090915062000dba908462001935565b949350505050565b60008062000dcf62001478565b6000948552602090815260408086206001600160a01b03959095168652939052505090205460ff1690565b600062000e0662001943565b805490915060ff600160401b82041615906001600160401b031660008115801562000e2e5750825b90506000826001600160401b0316600114801562000e4b5750303b155b90508115801562000e5a575080155b1562000e795760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b0319166001178555831562000ea357845460ff60401b1916600160401b1785555b62000ead62001967565b62000eb76200197b565b62000ec16200197b565b62000ece60008c6200149c565b5062000eea60008051602062002edf8339815191528b6200149c565b5062000f0660008051602062002e9f8339815191528a6200149c565b5062000f2260008051602062002e7f833981519152896200149c565b50600062000f2f62001327565b6002810180546001600160a01b0319166001600160a01b038b161790556003810188905568056bc75e2d6310000060019091015550831562000fab57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b60008062000fc562001327565b546001600160a01b031692915050565b60008051602062002e7f83398151915262000ff0816200134b565b816001600160a01b03163b60000362001020578160405163c9c10a6160e01b8152600401620008a4919062002448565b60006200102c62000b45565b9050620010398362001985565b826001600160a01b0316816001600160a01b03167f8752daf55fa0ccd919c149bbc809abaad4433f02ba7aa93ac6d5acfd2f8dc22c60405160405180910390a3505050565b606060006200108c620014e5565b905060006200109b82620018b6565b9050600081516001600160401b03811115620010bb57620010bb62002497565b604051908082528060200260200182016040528015620010f057816020015b6060815260200190600190039081620010da5790505b50905060005b8251811015620011eb578360020160008483815181106200111b576200111b62002862565b6020026020010151815260200190815260200160002080546200113e9062002826565b80601f01602080910402602001604051908101604052809291908181526020018280546200116c9062002826565b8015620011bd5780601f106200119157610100808354040283529160200191620011bd565b820191906000526020600020905b8154815290600101906020018083116200119f57829003601f168201915b5050505050828281518110620011d757620011d762002862565b6020908102919091010152600101620010f6565b509392505050565b6000806200120062001327565b6001015492915050565b6000806200121762001911565b60008481526020829052604090209091506200123390620019b6565b9392505050565b620012458262000999565b62001250816200134b565b62000a15838362001517565b60008051602062002e5f83398151915262001277816200134b565b60006200128362000ae5565b90506200129083620019c1565b604051839082907fc1fec27bbb8c533fedd3d449016c429341bfc0df21a9600e6162605e08f1c78f90600090a3505050565b6000620012ce620019d7565b620012d862001a10565b620012e4838362001a39565b90506200083362001c79565b60006001600160e01b03198216637965db0b60e01b14806200083357506301ffc9a760e01b6001600160e01b031983161462000833565b7f2b421af391835920c41e77b6810f6e715f5b713c17bc590f55de6a7d3912e80090565b62000b21813362001c8c565b60006200136362001327565b80546001600160a01b0319166001600160a01b03939093169290921790915550565b6000816040516020016200139a919062002808565b6040516020818303038152906040528051906020012090506000620013be620014e5565b90506000620013ce828462001cc9565b905080620013f35783604051633dad0df560e11b8152600401620008a491906200267b565b600083815260028301602052604090206200140f8582620028cc565b5082826003018560405162001425919062002808565b9081526020016040518091039020819055507fbad43a69707ac20dd539f3163b927e83baef6e967f2c95432129b1ded416645884846040516200146a92919062002998565b60405180910390a150505050565b7f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680090565b600080620014a962001911565b90506000620014b9858562001cd7565b9050801562000dba576000858152602083905260409020620014dc908562001d80565b50949350505050565b7f563e037355fff0507705f481e4b362e4c3996a3b57d07307deabfca3d816860090565b600062001233838362001d97565b6000806200152462001911565b9050600062001534858562001daf565b9050801562000dba576000858152602083905260409020620014dc908562001e2d565b6200156162001e44565b60006200156d62001783565b805460ff1916815590507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051620015a9919062002448565b60405180910390a150565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806200163e57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166200163260008051602062002ebf833981519152546001600160a01b031690565b6001600160a01b031614155b156200165d5760405163703e46dd60e11b815260040160405180910390fd5b565b60008051602062002e9f83398151915262000931816200134b565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015620016d7575060408051601f3d908101601f19168201909252620016d491810190620029bc565b60015b620016f95781604051634c9c8ce360e01b8152600401620008a4919062002448565b60008051602062002ebf83398151915281146200172d57604051632a87526960e21b815260048101829052602401620008a4565b62000ae0838362001e6c565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146200165d5760405163703e46dd60e11b815260040160405180910390fd5b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330090565b600081604051602001620017bc919062002808565b6040516020818303038152906040528051906020012090506000620017e0620014e5565b90506000620017f0828462001ec9565b905080620018115760405163162e926760e11b815260040160405180910390fd5b600083815260028301602052604081206200182c91620023b4565b816003018460405162001840919062002808565b9081526020016040518091039020600090557f57158eaa7e642cefd761327d5cd6c147ddaad706ec257f90f4d8b59b3d365eb784846040516200146a92919062002998565b60006200189162001327565b60020180546001600160a01b0319166001600160a01b03939093169290921790915550565b60606000620012338362001ed7565b620018cf62001a10565b6000620018db62001783565b805460ff1916600117815590507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586200159a3390565b7fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e8237170593200090565b600062001233838362001f35565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0090565b6200197162001f62565b6200165d62001f8a565b6200165d62001f62565b60006200199162001327565b60040180546001600160a01b0319166001600160a01b03939093169290921790915550565b600062000833825490565b6000620019cd62001327565b6003019190915550565b6000620019e362001fab565b80549091506001190162001a0a57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b62001a1a62000c68565b156200165d5760405163d93c066560e01b815260040160405180910390fd5b60006001600160a01b03831662001a67578260405163715397cd60e11b8152600401620008a4919062002448565b600062001a73620011f3565b90508034101562001aa1576040516353f01c6360e11b815260048101829052346024820152604401620008a4565b600062001aad62000fb8565b9050806001600160a01b03163b60000362001adf57806040516337766f4360e11b8152600401620008a4919062002448565b600062001aeb62000b45565b9050806001600160a01b03163b60000362001b1d578060405163c9c10a6160e01b8152600401620008a4919062002448565b60008260405162001b2e90620023f3565b6001600160a01b039091168152604060208201819052600090820152606001604051809103906000f08015801562001b6a573d6000803e3d6000fd5b506040516333e1a22360e01b81523060048201526001600160a01b0384811660248301526044820187905289811660648301528881166084830152919250908216906333e1a2239060a401600060405180830381600087803b15801562001bd057600080fd5b505af115801562001be5573d6000803e3d6000fd5b5050604080518082019091526001815233602082015262001c0a925083915062001fcf565b62001c2560008051602062002f1f833981519152826200149c565b5062001c3b6001600160a01b0382163462002032565b6040516001600160a01b038216907f22de16ef21e3a33810fbcaf0e737ab9c9e2854fa565d8535041456c789afcd9390600090a29695505050505050565b600062001c8562001fab565b6001905550565b62001c98828262000dc2565b620009315760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401620008a4565b6000620012338383620020cf565b60008062001ce462001478565b905062001cf2848462000dc2565b62001d75576000848152602082815260408083206001600160a01b03871684529091529020805460ff1916600117905562001d2a3390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505062000833565b600091505062000833565b600062001233836001600160a01b038416620020cf565b60009081526001919091016020526040902054151590565b60008062001dbc62001478565b905062001dca848462000dc2565b1562001d75576000848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505062000833565b600062001233836001600160a01b0384166200211e565b62001e4e62000c68565b6200165d57604051638dfc202b60e01b815260040160405180910390fd5b62001e778262002217565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511562001ebf5762000ae0828262002277565b62000931620022f3565b60006200123383836200211e565b60608160000180548060200260200160405190810160405280929190818152602001828054801562001f2957602002820191906000526020600020905b81548152602001906001019080831162001f14575b50505050509050919050565b600082600001828154811062001f4f5762001f4f62002862565b9060005260206000200154905092915050565b62001f6c62002313565b6200165d57604051631afcd79f60e31b815260040160405180910390fd5b62001f9462001f62565b600062001fa062001783565b805460ff1916905550565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0090565b600062001fdb62001327565b6001600160a01b03938416600090815260059091016020908152604090912083518154929094015190941661010002610100600160a81b0319931515939093166001600160a81b0319909116179190911790915550565b8047101562002058573060405163cd78605960e01b8152600401620008a4919062002448565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114620020a7576040519150601f19603f3d011682016040523d82523d6000602084013e620020ac565b606091505b505090508062000ae057604051630a12f52160e11b815260040160405180910390fd5b6000620020dd838362001d97565b620021155750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000833565b50600062000833565b6000818152600183016020526040812054801562001d7557600062002145600183620029d6565b85549091506000906200215b90600190620029d6565b9050808214620021c75760008660000182815481106200217f576200217f62002862565b9060005260206000200154905080876000018481548110620021a557620021a562002862565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620021db57620021db620029f8565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000833565b806001600160a01b03163b600003620022475780604051634c9c8ce360e01b8152600401620008a4919062002448565b60008051602062002ebf83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405162002296919062002808565b600060405180830381855af49150503d8060008114620022d3576040519150601f19603f3d011682016040523d82523d6000602084013e620022d8565b606091505b5091509150620022ea8583836200232f565b95945050505050565b34156200165d5760405163b398979f60e01b815260040160405180910390fd5b60006200231f62001943565b54600160401b900460ff16919050565b606082620023485762002342826200238a565b62001233565b81511580156200236057506001600160a01b0384163b155b15620023835783604051639996b31560e01b8152600401620008a4919062002448565b5092915050565b8051156200239b5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b508054620023c29062002826565b6000825580601f10620023d3575050565b601f01602090049060005260206000209081019062000b21919062002401565b6104108062002a0f83390190565b5b8082111562002418576000815560010162002402565b5090565b6000602082840312156200242f57600080fd5b81356001600160e01b0319811681146200123357600080fd5b6001600160a01b0391909116815260200190565b80356001600160a01b03811681146200247457600080fd5b919050565b6000602082840312156200248c57600080fd5b62001233826200245c565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b0380841115620024ca57620024ca62002497565b604051601f8501601f19908116603f01168101908282118183101715620024f557620024f562002497565b816040528093508581528686860111156200250f57600080fd5b858560208301376000602087830101525050509392505050565b6000602082840312156200253c57600080fd5b81356001600160401b038111156200255357600080fd5b8201601f810184136200256557600080fd5b62000dba84823560208401620024ad565b6000602082840312156200258957600080fd5b5035919050565b60008060408385031215620025a457600080fd5b82359150620025b6602084016200245c565b90509250929050565b60008060408385031215620025d357600080fd5b620025de836200245c565b915060208301356001600160401b03811115620025fa57600080fd5b8301601f810185136200260c57600080fd5b6200261d85823560208401620024ad565b9150509250929050565b60005b83811015620026445781810151838201526020016200262a565b50506000910152565b600081518084526200266781602086016020860162002627565b601f01601f19169290920160200192915050565b6020815260006200123360208301846200264d565b6020808252825182820181905260009190848201906040850190845b81811015620026ca57835183529284019291840191600101620026ac565b50909695505050505050565b60008060408385031215620026ea57600080fd5b50508035926020909101359150565b60008060008060008060c087890312156200271357600080fd5b6200271e876200245c565b95506200272e602088016200245c565b94506200273e604088016200245c565b93506200274e606088016200245c565b92506200275e608088016200245c565b915060a087013590509295509295509295565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015620027cc57603f19888603018452620027b98583516200264d565b945092850192908501906001016200279a565b5092979650505050505050565b60008060408385031215620027ed57600080fd5b620027f8836200245c565b9150620025b6602084016200245c565b600082516200281c81846020870162002627565b9190910192915050565b600181811c908216806200283b57607f821691505b6020821081036200285c57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b601f82111562000ae0576000816000526020600020601f850160051c81016020861015620028a35750805b601f850160051c820191505b81811015620028c457828155600101620028af565b505050505050565b81516001600160401b03811115620028e857620028e862002497565b6200290081620028f9845462002826565b8462002878565b602080601f8311600181146200293857600084156200291f5750858301515b600019600386901b1c1916600185901b178555620028c4565b600085815260208120601f198616915b82811015620029695788860151825594840194600190910190840162002948565b5085821015620029885787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000620029ad60408301856200264d565b90508260208301529392505050565b600060208284031215620029cf57600080fd5b5051919050565b818103818111156200083357634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fdfe60806040526040516104103803806104108339810160408190526100229161025a565b61002c8282610033565b5050610358565b61003c82610092565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610086576100818282610109565b505050565b61008e610180565b5050565b806001600160a01b03163b6000036100c85780604051634c9c8ce360e01b81526004016100bf9190610328565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610126919061033c565b600060405180830381855af49150503d8060008114610161576040519150601f19603f3d011682016040523d82523d6000602084013e610166565b606091505b5090925090506101778583836101a1565b95945050505050565b341561019f5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b6576101b1826101f7565b6101f0565b81511580156101cd57506001600160a01b0384163b155b156101ed5783604051639996b31560e01b81526004016100bf9190610328565b50805b9392505050565b8051156102075780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b600052604160045260246000fd5b60005b83811015610251578181015183820152602001610239565b50506000910152565b6000806040838503121561026d57600080fd5b82516001600160a01b038116811461028457600080fd5b60208401519092506001600160401b03808211156102a157600080fd5b818501915085601f8301126102b557600080fd5b8151818111156102c7576102c7610220565b604051601f8201601f19908116603f011681019083821181831017156102ef576102ef610220565b8160405282815288602084870101111561030857600080fd5b610319836020830160208801610236565b80955050505050509250929050565b6001600160a01b0391909116815260200190565b6000825161034e818460208701610236565b9190910192915050565b60aa806103666000396000f3fe6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea2646970667358221220e704d381a2ce0387b276e1f01c87ad61ca30b2c8b219afb40e2ddf5bcf16086164736f6c6343000818003330f3325e23b502dce693b147d37de928d14dd5ab09bbc928fb79867329ac5b83dccfb718b018e1b06f849958baf67b0b252302f06a69871f72c5127ee92f659d349eec46d2c564a125684d1934a6120a70cc341d3a26d362e358a775e07dec176a42249708403f5ed28bf492facd11e85bc1054e6c27c155ed468f6ff4f7ecd0189ab7a9244df0848122154315af71fe140f3db0fe014031783b0946b8c9d2e3360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a819590c814c6d279357359f817d25adb06a7b9f6e493592b7d3b8bb268adb6764f22871c78b70c8896c7119179fc4e9b6f4cf323f8db6eadb7d79007d1e00c3fa26469706673582212204a7231d4ccf265a64d1dfd7340f540b8a8e32f79618d47ebe892505b2da3fab164736f6c63430008180033",
+ "deployedBytecode": "0x608060405260043610620002185760003560e01c806301601d2f146200021d57806301ffc9a714620002555780630470d3ac146200028b57806309766da214620002b25780630d6115d014620002d957806312b357b514620002fe5780631c2b3afc1462000323578063248a9ca314620003485780632cec1a06146200036d5780632f2ff15d1462000392578063352af39a14620003b757806336568abe14620003dc5780633c55593814620004015780633f4ba83a146200041957806340df8d8414620004315780634cba593a14620004565780634f1ef286146200047b5780634f3f4639146200049257806352d1902d14620004aa5780635a81a62614620004c25780635c975abb14620004f65780635e818619146200050e5780636cd5687814620005335780637fa3465714620005585780638127f465146200057d5780638456cb5914620005a45780639010d07c14620005bc57806391d1485414620005e157806392cf833f146200060657806395b6ef0c146200062b5780639d825bc51462000650578063a217fddf1462000668578063ad3cb1cc146200067f578063b289819c14620006b2578063c17e30bf14620006d7578063c2a1db7814620006fc578063c39409e11462000723578063ca15c873146200073b578063d547741f1462000760578063e63ab1e91462000785578063f72c0d8b14620007aa578063f85b4a9c14620007cf578063fd2fbd5214620007f4575b600080fd5b3480156200022a57600080fd5b506200024260008051602062002e1f83398151915281565b6040519081526020015b60405180910390f35b3480156200026257600080fd5b506200027a620002743660046200241c565b6200080b565b60405190151581526020016200024c565b3480156200029857600080fd5b50620002a362000839565b6040516200024c919062002448565b348015620002bf57600080fd5b50620002d7620002d136600462002479565b62000859565b005b348015620002e657600080fd5b50620002d7620002f836600462002529565b6200090b565b3480156200030b57600080fd5b506200027a6200031d36600462002479565b62000935565b3480156200033057600080fd5b50620002d76200034236600462002576565b62000967565b3480156200035557600080fd5b50620002426200036736600462002576565b62000999565b3480156200037a57600080fd5b50620002a36200038c36600462002479565b620009bb565b3480156200039f57600080fd5b50620002d7620003b136600462002590565b620009f3565b348015620003c457600080fd5b5062000242620003d636600462002529565b62000a1b565b348015620003e957600080fd5b50620002d7620003fb36600462002590565b62000aaa565b3480156200040e57600080fd5b506200024262000ae5565b3480156200042657600080fd5b50620002d762000afc565b3480156200043e57600080fd5b506200024260008051602062002eff83398151915281565b3480156200046357600080fd5b506200024260008051602062002e5f83398151915281565b620002d76200048c366004620025bf565b62000b24565b3480156200049f57600080fd5b50620002a362000b45565b348015620004b757600080fd5b506200024262000b65565b348015620004cf57600080fd5b50620004e7620004e136600462002576565b62000b85565b6040516200024c91906200267b565b3480156200050357600080fd5b506200027a62000c68565b3480156200051b57600080fd5b50620002d76200052d36600462002529565b62000c7f565b3480156200054057600080fd5b50620002d76200055236600462002479565b62000ca5565b3480156200056557600080fd5b506200024260008051602062002f1f83398151915281565b3480156200058a57600080fd5b506200059562000d4a565b6040516200024c919062002690565b348015620005b157600080fd5b50620002d762000d6b565b348015620005c957600080fd5b50620002a3620005db366004620026d6565b62000d90565b348015620005ee57600080fd5b506200027a6200060036600462002590565b62000dc2565b3480156200061357600080fd5b506200024260008051602062002e3f83398151915281565b3480156200063857600080fd5b50620002d76200064a366004620026f9565b62000dfa565b3480156200065d57600080fd5b50620002a362000fb8565b3480156200067557600080fd5b5062000242600081565b3480156200068c57600080fd5b50620004e7604051806040016040528060058152602001640352e302e360dc1b81525081565b348015620006bf57600080fd5b506200024260008051602062002e7f83398151915281565b348015620006e457600080fd5b50620002d7620006f636600462002479565b62000fd5565b3480156200070957600080fd5b50620007146200107e565b6040516200024c919062002771565b3480156200073057600080fd5b5062000242620011f3565b3480156200074857600080fd5b50620002426200075a36600462002576565b6200120a565b3480156200076d57600080fd5b50620002d76200077f36600462002590565b6200123a565b3480156200079257600080fd5b506200024260008051602062002edf83398151915281565b348015620007b757600080fd5b506200024260008051602062002e9f83398151915281565b348015620007dc57600080fd5b50620002d7620007ee36600462002576565b6200125c565b620002a362000805366004620027d9565b620012c2565b60006001600160e01b03198216635a05180f60e01b14806200083357506200083382620012f0565b92915050565b6000806200084662001327565b600201546001600160a01b031692915050565b60008051602062002e7f83398151915262000874816200134b565b816001600160a01b03163b600003620008ad57816040516337766f4360e11b8152600401620008a4919062002448565b60405180910390fd5b6000620008b962000fb8565b9050620008c68362001357565b826001600160a01b0316816001600160a01b03167fecd599290ada9c149ae0fb600bc6ada3c103a716eadb877b5341b7d298b62d9360405160405180910390a3505050565b60008051602062002e3f83398151915262000926816200134b565b620009318262001385565b5050565b6000806200094262001327565b6001600160a01b03909316600090815260059093016020525050604090205460ff1690565b60008051602062002e1f83398151915262000982816200134b565b60006200098e62001327565b600101929092555050565b600080620009a662001478565b60009384526020525050604090206001015490565b600080620009c862001327565b6001600160a01b03938416600090815260059091016020526040902054610100900490921692915050565b620009fe8262000999565b62000a09816200134b565b62000a1583836200149c565b50505050565b60008062000a28620014e5565b905062000a618360405160200162000a41919062002808565b60408051601f198184030181529190528051602090910120829062001509565b62000a7f5760405163162e926760e11b815260040160405180910390fd5b806003018360405162000a93919062002808565b908152602001604051809103902054915050919050565b6001600160a01b038116331462000ad45760405163334bd91960e11b815260040160405180910390fd5b62000ae0828262001517565b505050565b60008062000af262001327565b6003015492915050565b60008051602062002edf83398151915262000b17816200134b565b62000b2162001557565b50565b62000b2e620015b4565b62000b39826200165f565b6200093182826200167a565b60008062000b5262001327565b600401546001600160a01b031692915050565b600062000b7162001739565b5060008051602062002ebf83398151915290565b6060600062000b93620014e5565b905062000ba1818462001509565b62000bbf5760405163162e926760e11b815260040160405180910390fd5b60008381526002820160205260409020805462000bdc9062002826565b80601f016020809104026020016040519081016040528092919081815260200182805462000c0a9062002826565b801562000c5b5780601f1062000c2f5761010080835404028352916020019162000c5b565b820191906000526020600020905b81548152906001019060200180831162000c3d57829003601f168201915b5050505050915050919050565b60008062000c7562001783565b5460ff1692915050565b60008051602062002e3f83398151915262000c9a816200134b565b6200093182620017a7565b60008051602062002eff83398151915262000cc0816200134b565b6001600160a01b03821662000cec578160405163220b4f1160e11b8152600401620008a4919062002448565b600062000cf862000839565b905062000d058362001885565b826001600160a01b0316816001600160a01b03167f88bf70d4f3c446213b5064d7cfe95ec0ed196748f014c19a833117bac32468fd60405160405180910390a3505050565b6060600062000d58620014e5565b905062000d6581620018b6565b91505090565b60008051602062002edf83398151915262000d86816200134b565b62000b21620018c5565b60008062000d9d62001911565b600085815260208290526040902090915062000dba908462001935565b949350505050565b60008062000dcf62001478565b6000948552602090815260408086206001600160a01b03959095168652939052505090205460ff1690565b600062000e0662001943565b805490915060ff600160401b82041615906001600160401b031660008115801562000e2e5750825b90506000826001600160401b0316600114801562000e4b5750303b155b90508115801562000e5a575080155b1562000e795760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b0319166001178555831562000ea357845460ff60401b1916600160401b1785555b62000ead62001967565b62000eb76200197b565b62000ec16200197b565b62000ece60008c6200149c565b5062000eea60008051602062002edf8339815191528b6200149c565b5062000f0660008051602062002e9f8339815191528a6200149c565b5062000f2260008051602062002e7f833981519152896200149c565b50600062000f2f62001327565b6002810180546001600160a01b0319166001600160a01b038b161790556003810188905568056bc75e2d6310000060019091015550831562000fab57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b60008062000fc562001327565b546001600160a01b031692915050565b60008051602062002e7f83398151915262000ff0816200134b565b816001600160a01b03163b60000362001020578160405163c9c10a6160e01b8152600401620008a4919062002448565b60006200102c62000b45565b9050620010398362001985565b826001600160a01b0316816001600160a01b03167f8752daf55fa0ccd919c149bbc809abaad4433f02ba7aa93ac6d5acfd2f8dc22c60405160405180910390a3505050565b606060006200108c620014e5565b905060006200109b82620018b6565b9050600081516001600160401b03811115620010bb57620010bb62002497565b604051908082528060200260200182016040528015620010f057816020015b6060815260200190600190039081620010da5790505b50905060005b8251811015620011eb578360020160008483815181106200111b576200111b62002862565b6020026020010151815260200190815260200160002080546200113e9062002826565b80601f01602080910402602001604051908101604052809291908181526020018280546200116c9062002826565b8015620011bd5780601f106200119157610100808354040283529160200191620011bd565b820191906000526020600020905b8154815290600101906020018083116200119f57829003601f168201915b5050505050828281518110620011d757620011d762002862565b6020908102919091010152600101620010f6565b509392505050565b6000806200120062001327565b6001015492915050565b6000806200121762001911565b60008481526020829052604090209091506200123390620019b6565b9392505050565b620012458262000999565b62001250816200134b565b62000a15838362001517565b60008051602062002e5f83398151915262001277816200134b565b60006200128362000ae5565b90506200129083620019c1565b604051839082907fc1fec27bbb8c533fedd3d449016c429341bfc0df21a9600e6162605e08f1c78f90600090a3505050565b6000620012ce620019d7565b620012d862001a10565b620012e4838362001a39565b90506200083362001c79565b60006001600160e01b03198216637965db0b60e01b14806200083357506301ffc9a760e01b6001600160e01b031983161462000833565b7f2b421af391835920c41e77b6810f6e715f5b713c17bc590f55de6a7d3912e80090565b62000b21813362001c8c565b60006200136362001327565b80546001600160a01b0319166001600160a01b03939093169290921790915550565b6000816040516020016200139a919062002808565b6040516020818303038152906040528051906020012090506000620013be620014e5565b90506000620013ce828462001cc9565b905080620013f35783604051633dad0df560e11b8152600401620008a491906200267b565b600083815260028301602052604090206200140f8582620028cc565b5082826003018560405162001425919062002808565b9081526020016040518091039020819055507fbad43a69707ac20dd539f3163b927e83baef6e967f2c95432129b1ded416645884846040516200146a92919062002998565b60405180910390a150505050565b7f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680090565b600080620014a962001911565b90506000620014b9858562001cd7565b9050801562000dba576000858152602083905260409020620014dc908562001d80565b50949350505050565b7f563e037355fff0507705f481e4b362e4c3996a3b57d07307deabfca3d816860090565b600062001233838362001d97565b6000806200152462001911565b9050600062001534858562001daf565b9050801562000dba576000858152602083905260409020620014dc908562001e2d565b6200156162001e44565b60006200156d62001783565b805460ff1916815590507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051620015a9919062002448565b60405180910390a150565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806200163e57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166200163260008051602062002ebf833981519152546001600160a01b031690565b6001600160a01b031614155b156200165d5760405163703e46dd60e11b815260040160405180910390fd5b565b60008051602062002e9f83398151915262000931816200134b565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015620016d7575060408051601f3d908101601f19168201909252620016d491810190620029bc565b60015b620016f95781604051634c9c8ce360e01b8152600401620008a4919062002448565b60008051602062002ebf83398151915281146200172d57604051632a87526960e21b815260048101829052602401620008a4565b62000ae0838362001e6c565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146200165d5760405163703e46dd60e11b815260040160405180910390fd5b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330090565b600081604051602001620017bc919062002808565b6040516020818303038152906040528051906020012090506000620017e0620014e5565b90506000620017f0828462001ec9565b905080620018115760405163162e926760e11b815260040160405180910390fd5b600083815260028301602052604081206200182c91620023b4565b816003018460405162001840919062002808565b9081526020016040518091039020600090557f57158eaa7e642cefd761327d5cd6c147ddaad706ec257f90f4d8b59b3d365eb784846040516200146a92919062002998565b60006200189162001327565b60020180546001600160a01b0319166001600160a01b03939093169290921790915550565b60606000620012338362001ed7565b620018cf62001a10565b6000620018db62001783565b805460ff1916600117815590507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586200159a3390565b7fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e8237170593200090565b600062001233838362001f35565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0090565b6200197162001f62565b6200165d62001f8a565b6200165d62001f62565b60006200199162001327565b60040180546001600160a01b0319166001600160a01b03939093169290921790915550565b600062000833825490565b6000620019cd62001327565b6003019190915550565b6000620019e362001fab565b80549091506001190162001a0a57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b62001a1a62000c68565b156200165d5760405163d93c066560e01b815260040160405180910390fd5b60006001600160a01b03831662001a67578260405163715397cd60e11b8152600401620008a4919062002448565b600062001a73620011f3565b90508034101562001aa1576040516353f01c6360e11b815260048101829052346024820152604401620008a4565b600062001aad62000fb8565b9050806001600160a01b03163b60000362001adf57806040516337766f4360e11b8152600401620008a4919062002448565b600062001aeb62000b45565b9050806001600160a01b03163b60000362001b1d578060405163c9c10a6160e01b8152600401620008a4919062002448565b60008260405162001b2e90620023f3565b6001600160a01b039091168152604060208201819052600090820152606001604051809103906000f08015801562001b6a573d6000803e3d6000fd5b506040516333e1a22360e01b81523060048201526001600160a01b0384811660248301526044820187905289811660648301528881166084830152919250908216906333e1a2239060a401600060405180830381600087803b15801562001bd057600080fd5b505af115801562001be5573d6000803e3d6000fd5b5050604080518082019091526001815233602082015262001c0a925083915062001fcf565b62001c2560008051602062002f1f833981519152826200149c565b5062001c3b6001600160a01b0382163462002032565b6040516001600160a01b038216907f22de16ef21e3a33810fbcaf0e737ab9c9e2854fa565d8535041456c789afcd9390600090a29695505050505050565b600062001c8562001fab565b6001905550565b62001c98828262000dc2565b620009315760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401620008a4565b6000620012338383620020cf565b60008062001ce462001478565b905062001cf2848462000dc2565b62001d75576000848152602082815260408083206001600160a01b03871684529091529020805460ff1916600117905562001d2a3390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600191505062000833565b600091505062000833565b600062001233836001600160a01b038416620020cf565b60009081526001919091016020526040902054151590565b60008062001dbc62001478565b905062001dca848462000dc2565b1562001d75576000848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4600191505062000833565b600062001233836001600160a01b0384166200211e565b62001e4e62000c68565b6200165d57604051638dfc202b60e01b815260040160405180910390fd5b62001e778262002217565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511562001ebf5762000ae0828262002277565b62000931620022f3565b60006200123383836200211e565b60608160000180548060200260200160405190810160405280929190818152602001828054801562001f2957602002820191906000526020600020905b81548152602001906001019080831162001f14575b50505050509050919050565b600082600001828154811062001f4f5762001f4f62002862565b9060005260206000200154905092915050565b62001f6c62002313565b6200165d57604051631afcd79f60e31b815260040160405180910390fd5b62001f9462001f62565b600062001fa062001783565b805460ff1916905550565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0090565b600062001fdb62001327565b6001600160a01b03938416600090815260059091016020908152604090912083518154929094015190941661010002610100600160a81b0319931515939093166001600160a81b0319909116179190911790915550565b8047101562002058573060405163cd78605960e01b8152600401620008a4919062002448565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114620020a7576040519150601f19603f3d011682016040523d82523d6000602084013e620020ac565b606091505b505090508062000ae057604051630a12f52160e11b815260040160405180910390fd5b6000620020dd838362001d97565b620021155750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000833565b50600062000833565b6000818152600183016020526040812054801562001d7557600062002145600183620029d6565b85549091506000906200215b90600190620029d6565b9050808214620021c75760008660000182815481106200217f576200217f62002862565b9060005260206000200154905080876000018481548110620021a557620021a562002862565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620021db57620021db620029f8565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000833565b806001600160a01b03163b600003620022475780604051634c9c8ce360e01b8152600401620008a4919062002448565b60008051602062002ebf83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405162002296919062002808565b600060405180830381855af49150503d8060008114620022d3576040519150601f19603f3d011682016040523d82523d6000602084013e620022d8565b606091505b5091509150620022ea8583836200232f565b95945050505050565b34156200165d5760405163b398979f60e01b815260040160405180910390fd5b60006200231f62001943565b54600160401b900460ff16919050565b606082620023485762002342826200238a565b62001233565b81511580156200236057506001600160a01b0384163b155b15620023835783604051639996b31560e01b8152600401620008a4919062002448565b5092915050565b8051156200239b5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b508054620023c29062002826565b6000825580601f10620023d3575050565b601f01602090049060005260206000209081019062000b21919062002401565b6104108062002a0f83390190565b5b8082111562002418576000815560010162002402565b5090565b6000602082840312156200242f57600080fd5b81356001600160e01b0319811681146200123357600080fd5b6001600160a01b0391909116815260200190565b80356001600160a01b03811681146200247457600080fd5b919050565b6000602082840312156200248c57600080fd5b62001233826200245c565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b0380841115620024ca57620024ca62002497565b604051601f8501601f19908116603f01168101908282118183101715620024f557620024f562002497565b816040528093508581528686860111156200250f57600080fd5b858560208301376000602087830101525050509392505050565b6000602082840312156200253c57600080fd5b81356001600160401b038111156200255357600080fd5b8201601f810184136200256557600080fd5b62000dba84823560208401620024ad565b6000602082840312156200258957600080fd5b5035919050565b60008060408385031215620025a457600080fd5b82359150620025b6602084016200245c565b90509250929050565b60008060408385031215620025d357600080fd5b620025de836200245c565b915060208301356001600160401b03811115620025fa57600080fd5b8301601f810185136200260c57600080fd5b6200261d85823560208401620024ad565b9150509250929050565b60005b83811015620026445781810151838201526020016200262a565b50506000910152565b600081518084526200266781602086016020860162002627565b601f01601f19169290920160200192915050565b6020815260006200123360208301846200264d565b6020808252825182820181905260009190848201906040850190845b81811015620026ca57835183529284019291840191600101620026ac565b50909695505050505050565b60008060408385031215620026ea57600080fd5b50508035926020909101359150565b60008060008060008060c087890312156200271357600080fd5b6200271e876200245c565b95506200272e602088016200245c565b94506200273e604088016200245c565b93506200274e606088016200245c565b92506200275e608088016200245c565b915060a087013590509295509295509295565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015620027cc57603f19888603018452620027b98583516200264d565b945092850192908501906001016200279a565b5092979650505050505050565b60008060408385031215620027ed57600080fd5b620027f8836200245c565b9150620025b6602084016200245c565b600082516200281c81846020870162002627565b9190910192915050565b600181811c908216806200283b57607f821691505b6020821081036200285c57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b601f82111562000ae0576000816000526020600020601f850160051c81016020861015620028a35750805b601f850160051c820191505b81811015620028c457828155600101620028af565b505050505050565b81516001600160401b03811115620028e857620028e862002497565b6200290081620028f9845462002826565b8462002878565b602080601f8311600181146200293857600084156200291f5750858301515b600019600386901b1c1916600185901b178555620028c4565b600085815260208120601f198616915b82811015620029695788860151825594840194600190910190840162002948565b5085821015620029885787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000620029ad60408301856200264d565b90508260208301529392505050565b600060208284031215620029cf57600080fd5b5051919050565b818103818111156200083357634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fdfe60806040526040516104103803806104108339810160408190526100229161025a565b61002c8282610033565b5050610358565b61003c82610092565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2805115610086576100818282610109565b505050565b61008e610180565b5050565b806001600160a01b03163b6000036100c85780604051634c9c8ce360e01b81526004016100bf9190610328565b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b031684604051610126919061033c565b600060405180830381855af49150503d8060008114610161576040519150601f19603f3d011682016040523d82523d6000602084013e610166565b606091505b5090925090506101778583836101a1565b95945050505050565b341561019f5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b6576101b1826101f7565b6101f0565b81511580156101cd57506001600160a01b0384163b155b156101ed5783604051639996b31560e01b81526004016100bf9190610328565b50805b9392505050565b8051156102075780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b600052604160045260246000fd5b60005b83811015610251578181015183820152602001610239565b50506000910152565b6000806040838503121561026d57600080fd5b82516001600160a01b038116811461028457600080fd5b60208401519092506001600160401b03808211156102a157600080fd5b818501915085601f8301126102b557600080fd5b8151818111156102c7576102c7610220565b604051601f8201601f19908116603f011681019083821181831017156102ef576102ef610220565b8160405282815288602084870101111561030857600080fd5b610319836020830160208801610236565b80955050505050509250929050565b6001600160a01b0391909116815260200190565b6000825161034e818460208701610236565b9190910192915050565b60aa806103666000396000f3fe6080604052600a600c565b005b60186014601a565b6051565b565b6000604c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e808015606f573d6000f35b3d6000fdfea2646970667358221220e704d381a2ce0387b276e1f01c87ad61ca30b2c8b219afb40e2ddf5bcf16086164736f6c6343000818003330f3325e23b502dce693b147d37de928d14dd5ab09bbc928fb79867329ac5b83dccfb718b018e1b06f849958baf67b0b252302f06a69871f72c5127ee92f659d349eec46d2c564a125684d1934a6120a70cc341d3a26d362e358a775e07dec176a42249708403f5ed28bf492facd11e85bc1054e6c27c155ed468f6ff4f7ecd0189ab7a9244df0848122154315af71fe140f3db0fe014031783b0946b8c9d2e3360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a819590c814c6d279357359f817d25adb06a7b9f6e493592b7d3b8bb268adb6764f22871c78b70c8896c7119179fc4e9b6f4cf323f8db6eadb7d79007d1e00c3fa26469706673582212204a7231d4ccf265a64d1dfd7340f540b8a8e32f79618d47ebe892505b2da3fab164736f6c63430008180033",
+ "linkReferences": {},
+ "deployedLinkReferences": {}
+}
diff --git a/src/helpers/partnerConfigurationContext.tsx b/src/helpers/partnerConfigurationContext.tsx
new file mode 100644
index 00000000..8825ba05
--- /dev/null
+++ b/src/helpers/partnerConfigurationContext.tsx
@@ -0,0 +1,393 @@
+import { ethers } from 'ethers'
+import React, { createContext, useContext, useEffect, useReducer } from 'react'
+import { usePartnerConfig } from './usePartnerConfig'
+import { useSmartContract } from './useSmartContract'
+
+// Initial state
+const initialState = {
+ stepsConfig: [
+ {
+ step: 0,
+ title: 'Messenger configuration',
+ services: [],
+ paragraph:
+ 'This wizard will help you create and activate your Camino Messenger Account with Camino Messenger address. Once set up, your Camino Messenger address will be displayed on your partner detail page, enabling direct communication with other Camino Messenger users.',
+ distributor: { isDistributor: true, services: [] },
+ },
+ {
+ step: 1,
+ title: 'Supplier configuration',
+ type: 'supplier',
+ paragraph:
+ 'Configure services, set fees, and add specific details. Customize your setup by selecting or removing services below.',
+ isSupplier: false,
+ services: [],
+ },
+ {
+ step: 2,
+ type: 'distributor',
+ title: 'Distributor configuration',
+ paragraph:
+ 'Configure wanted services. Customize your setup by selecting or removing services below.',
+ services: [],
+ isDistributor: false,
+ },
+ { step: 3, title: 'Accepted currencies', isOffChain: false, isCam: false },
+ {
+ step: 4,
+ title: 'Review data',
+ paragraph:
+ 'Please take a moment to review the data we got from you and check if everything is correct. If needed you can change them now or later in your Camino Messenger preferences',
+ },
+ ],
+ balance: '0',
+ step: 0,
+ isAbleToCreateCMAccount: false,
+ registredServices: [],
+}
+
+// Action types
+export const actionTypes = {
+ ADD_SERVICE: 'ADD_SERVICE',
+ UPDATE_SUPPORTED_SERVICES: 'UPDATE_SUPPORTED_SERVICES',
+ UPDATE_WANTED_SERVICES: 'UPDATE_WANTED_SERVICES',
+ REMOVE_SERVICE: 'REMOVE_SERVICE',
+ UPDATE_STEP: 'UPDATE_STEP',
+ UPDATE_IS_SUPPLIER: 'UPDATE_IS_SUPPLIER',
+ ADD_CAPABILITIES: 'ADD_CAPABILITIES',
+ UPDATE_CAPABILITY: 'UPDATE_CAPABILITY',
+ UPDATE_RACK_RATES: 'UPDATE_RACK_RATES',
+ UPDATE_FEE: 'UPDATE_FEE',
+ UPDATE_IS_OFF_CHAIN: 'UPDATE_IS_OFF_CHAIN',
+ UPDATE_IS_CAM: 'UPDATE_IS_CAM',
+ UPDATE_IS_ABLE_TO_CREATE_MESSENGER_ACCOUNT: 'UPDATE_IS_ABLE_TO_CREATE_MESSENGER_ACCOUNT',
+ GET_ALL_REGISTRED_SERVICES: 'GET_ALL_REGISTRED_SERVICES',
+ UPDATE_BALANCE: 'UPDATE_BALANCE',
+ RESET_STATE: 'RESET_STATE',
+}
+
+// Reducer function
+export function reducer(state = initialState, action) {
+ switch (action.type) {
+ case actionTypes.ADD_SERVICE: {
+ const { step, newService } = action.payload
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map(item =>
+ item.step === step
+ ? {
+ ...item,
+ services: [...item.services, newService],
+ }
+ : item,
+ ),
+ }
+ }
+ case actionTypes.RESET_STATE:
+ const { initialState } = action.payload
+ return { ...state, ...initialState }
+ case actionTypes.UPDATE_SUPPORTED_SERVICES: {
+ const { services } = action.payload
+ if (!services || services.length < 1) return state
+ let parsedServices = services[0].map((service, index) => {
+ return {
+ name: service,
+ fee: ethers.formatEther(services[1][index][0]),
+ rackRates: services[1][index][1],
+ capabilities: services[1][index][2],
+ }
+ })
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map(item =>
+ item.step === 1
+ ? {
+ ...item,
+ isSupplier: parsedServices.length > 0 ? true : false,
+ services: parsedServices,
+ }
+ : item,
+ ),
+ }
+ }
+
+ case actionTypes.UPDATE_WANTED_SERVICES: {
+ const { wantedServices } = action.payload
+ if (!wantedServices || wantedServices.length < 1) return state
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map(item =>
+ item.step === 2
+ ? {
+ ...item,
+ isDistributor: wantedServices.length > 0 ? true : false,
+ services: wantedServices.map(elem => {
+ return { name: elem }
+ }),
+ }
+ : item,
+ ),
+ }
+ }
+
+ case actionTypes.REMOVE_SERVICE: {
+ const { step, serviceIndex } = action.payload
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map(item =>
+ item.step === step
+ ? {
+ ...item,
+ services: item.services.filter((_, index) => index !== serviceIndex),
+ }
+ : item,
+ ),
+ }
+ }
+
+ case actionTypes.UPDATE_IS_ABLE_TO_CREATE_MESSENGER_ACCOUNT: {
+ const { isAbleToCreateCMAccount } = action.payload
+ return {
+ ...state,
+ isAbleToCreateCMAccount,
+ }
+ }
+
+ case actionTypes.UPDATE_STEP: {
+ const { step } = action.payload
+ return {
+ ...state,
+ step,
+ }
+ }
+
+ case actionTypes.UPDATE_IS_OFF_CHAIN: {
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map(item =>
+ item.step === state.step
+ ? {
+ ...item,
+ isOffChain: !state.stepsConfig[state.step].isOffChain,
+ }
+ : item,
+ ),
+ }
+ }
+
+ case actionTypes.GET_ALL_REGISTRED_SERVICES: {
+ const { registredServices } = action.payload
+ return {
+ ...state,
+ registredServices,
+ }
+ }
+
+ case actionTypes.UPDATE_IS_CAM: {
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map(item =>
+ item.step === state.step
+ ? {
+ ...item,
+ isCam: !state.stepsConfig[state.step].isCam,
+ }
+ : item,
+ ),
+ }
+ }
+
+ case actionTypes.UPDATE_IS_SUPPLIER: {
+ if (state.step === 2) {
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map(item =>
+ item.step === state.step
+ ? {
+ ...item,
+ services: state.stepsConfig[state.step].isDistributor
+ ? []
+ : item.services,
+ isDistributor: !state.stepsConfig[state.step].isDistributor,
+ }
+ : item,
+ ),
+ }
+ }
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map(item =>
+ item.step === state.step
+ ? {
+ ...item,
+ services: state.stepsConfig[state.step].isSupplier
+ ? []
+ : item.services,
+ isSupplier: !state.stepsConfig[state.step].isSupplier,
+ }
+ : item,
+ ),
+ }
+ }
+
+ case actionTypes.UPDATE_RACK_RATES: {
+ const { step, serviceIndex } = action.payload
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map(item =>
+ item.step === state.step
+ ? {
+ ...item,
+ services: item.services.map((service, sIndex) =>
+ sIndex === serviceIndex
+ ? {
+ ...service,
+ rackRates:
+ !state.stepsConfig[step].services[serviceIndex]
+ .rackRates,
+ }
+ : service,
+ ),
+ }
+ : item,
+ ),
+ }
+ }
+
+ case actionTypes.ADD_CAPABILITIES: {
+ const { step, serviceIndex } = action.payload
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map((item, index) =>
+ index === step
+ ? {
+ ...item,
+ services: item.services.map((service, sIndex) =>
+ sIndex === serviceIndex
+ ? {
+ ...service,
+ capabilities: [...service.capabilities, ''],
+ }
+ : service,
+ ),
+ }
+ : item,
+ ),
+ }
+ }
+
+ case actionTypes.UPDATE_CAPABILITY: {
+ const { step, serviceIndex, capabilityIndex, newValue } = action.payload
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map((item, itemIndex) =>
+ itemIndex === step
+ ? {
+ ...item,
+ services: item.services.map((service, sIndex) =>
+ sIndex === serviceIndex
+ ? {
+ ...service,
+ capabilities: service.capabilities.map(
+ (capability, capIndex) =>
+ capIndex === capabilityIndex
+ ? newValue
+ : capability,
+ ),
+ }
+ : service,
+ ),
+ }
+ : item,
+ ),
+ }
+ }
+
+ case actionTypes.UPDATE_FEE: {
+ const { step, serviceIndex, newValue } = action.payload
+ return {
+ ...state,
+ stepsConfig: state.stepsConfig.map((item, itemIndex) =>
+ itemIndex === step
+ ? {
+ ...item,
+ services: item.services.map((service, sIndex) =>
+ sIndex === serviceIndex
+ ? {
+ ...service,
+ fee: newValue,
+ }
+ : service,
+ ),
+ }
+ : item,
+ ),
+ }
+ }
+ case actionTypes.UPDATE_BALANCE: {
+ const { newValue } = action.payload
+ return {
+ ...state,
+ balance: newValue,
+ }
+ }
+
+ default:
+ return state
+ }
+}
+
+// Create context
+const PartnerConfigContext = createContext()
+
+// Context provider component
+export const PartnerConfigurationProvider = ({ children }) => {
+ const [state, dispatch] = useReducer(reducer, initialState)
+ const partnerConfig = usePartnerConfig()
+ const { accountReadContract } = useSmartContract()
+
+ useEffect(() => {
+ if (partnerConfig.account) {
+ partnerConfig.getAllServices().then(result => {
+ dispatch({
+ type: actionTypes.GET_ALL_REGISTRED_SERVICES,
+ payload: {
+ registredServices: result,
+ },
+ })
+ })
+ }
+ }, [partnerConfig.account])
+
+ useEffect(() => {
+ if (accountReadContract) {
+ partnerConfig.getSupportedServices().then(res => {
+ dispatch({
+ type: actionTypes.UPDATE_SUPPORTED_SERVICES,
+ payload: { services: res },
+ })
+ })
+ partnerConfig.getWantedServices().then(res => {
+ dispatch({
+ type: actionTypes.UPDATE_WANTED_SERVICES,
+ payload: { wantedServices: res },
+ })
+ })
+ }
+ }, [accountReadContract])
+
+ return (
+
+ {children}
+
+ )
+}
+
+// Custom hook to use the Messenger context
+export const usePartnerConfigurationContext = () => {
+ const context = useContext(PartnerConfigContext)
+ if (context === undefined) {
+ throw new Error('useMessengerContext must be used within a MessengerProvider')
+ }
+ return context
+}
diff --git a/src/helpers/usePartnerConfig.tsx b/src/helpers/usePartnerConfig.tsx
new file mode 100644
index 00000000..df264c12
--- /dev/null
+++ b/src/helpers/usePartnerConfig.tsx
@@ -0,0 +1,329 @@
+import { ethers } from 'ethers'
+import { useCallback, useEffect } from 'react'
+import { useAppDispatch } from '../hooks/reduxHooks'
+import { updateCMAcocuntContract } from '../redux/slices/partner'
+import { useSmartContract } from './useSmartContract'
+
+export const usePartnerConfig = () => {
+ const {
+ readFromContract,
+ writeToContract,
+ account,
+ managerWriteContract,
+ setContractCMAccountAddress,
+ accountWriteContract,
+ managerReadContract,
+ wallet,
+ CMAccountCreated,
+ accountReadContract,
+ } = useSmartContract()
+
+ const dispatch = useAppDispatch()
+
+ async function CreateConfiguration(state) {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+ try {
+ let balance = ethers.parseEther(state.balance ? state.balance : '0')
+ let services = state.stepsConfig[1].services.map(elem => {
+ return {
+ ...elem,
+ fee: ethers.parseEther(elem.fee ? elem.fee : '0'),
+ capabilities: elem.capabilities.filter(item => item !== ''),
+ }
+ })
+ let wantedServices = state.stepsConfig[2].services.map(elem => elem.name)
+ let isOffChainPayement = state.stepsConfig[3].isOffChain
+ let isCam = state.stepsConfig[3].isCam
+
+ const tx = await writeToContract('manager', 'createCMAccount', account, account, {
+ value: balance,
+ })
+ const event = tx.logs.find(log => {
+ try {
+ return managerWriteContract.interface.parseLog(log).name === 'CMAccountCreated'
+ } catch (e) {
+ return false
+ }
+ })
+
+ const parsedEvent = managerWriteContract.interface.parseLog(event)
+ const cmAccountAddress = parsedEvent.args.account
+ setContractCMAccountAddress(cmAccountAddress)
+ await CMAccountCreated(
+ { services, wantedServices, isOffChainPayement },
+ cmAccountAddress,
+ )
+ return tx
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ }
+
+ const getAllServices = useCallback(async () => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+
+ try {
+ const services = await readFromContract('manager', 'getAllRegisteredServiceNames')
+ return services
+ } catch (error) {
+ console.error('Error getting All Services:', error)
+ throw error
+ }
+ }, [account, readFromContract])
+
+ const getSupportedServices = useCallback(async () => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+
+ try {
+ const services = await readFromContract('account', 'getSupportedServices')
+ return services
+ } catch (error) {
+ console.error('Error getting Supported Services:', error)
+ throw error
+ }
+ }, [account, readFromContract])
+
+ const getWantedServices = useCallback(async () => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+
+ try {
+ const wantedServices = await readFromContract('account', 'getWantedServices')
+ return wantedServices
+ } catch (error) {
+ console.error('Error getting All Wanted Services:', error)
+ throw error
+ }
+ }, [account, readFromContract])
+
+ const getListOfBots = useCallback(async () => {
+ try {
+ const CHEQUE_OPERATOR_ROLE = await readFromContract('account', 'CHEQUE_OPERATOR_ROLE')
+ const roleMemberCount = await readFromContract(
+ 'account',
+ 'getRoleMemberCount',
+ CHEQUE_OPERATOR_ROLE,
+ )
+
+ const botPromises = []
+ for (let i = 0; i < roleMemberCount; i++) {
+ botPromises.push(accountReadContract.getRoleMember(CHEQUE_OPERATOR_ROLE, i))
+ }
+
+ const bots = await Promise.all(botPromises)
+ return bots
+ } catch (error) {
+ throw error
+ }
+ }, [account, managerReadContract])
+
+ const isCMAccount = useCallback(async () => {
+ try {
+ const CMACCOUNT_ROLE = await readFromContract('manager', 'CMACCOUNT_ROLE')
+ const roleMemberCount = await readFromContract(
+ 'manager',
+ 'getRoleMemberCount',
+ CMACCOUNT_ROLE,
+ )
+ let i = 0
+ while (i < roleMemberCount) {
+ managerReadContract.getRoleMember(CMACCOUNT_ROLE, i).then(async role => {
+ readFromContract('manager', 'getCMAccountCreator', role).then(creator => {
+ if (creator === wallet.address) {
+ setContractCMAccountAddress(role)
+ dispatch(updateCMAcocuntContract(role))
+ }
+ })
+ })
+ i++
+ }
+
+ return
+ } catch (error) {
+ throw error
+ }
+ }, [account, managerReadContract])
+
+ useEffect(() => {
+ isCMAccount()
+ }, [wallet])
+
+ const addServices = useCallback(
+ async services => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+ try {
+ for (const service of services) {
+ const tx = await accountWriteContract.addService(
+ service.name,
+ ethers.parseEther(service.fee ? service.fee : '0'),
+ service.rackRates,
+ service.capabilities.filter(item => item !== ''),
+ )
+ const receipt = await tx.wait()
+ return receipt
+ }
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ },
+ [account, writeToContract],
+ )
+ const removeServices = useCallback(
+ async services => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+ try {
+ for (const service of services) {
+ const tx = await accountWriteContract.removeService(service.name)
+ const receipt = await tx.wait()
+ return receipt
+ }
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ },
+ [account, writeToContract],
+ )
+
+ const addMessengerBot = useCallback(
+ async address => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+ try {
+ const addMessengerBotTx = await accountWriteContract.addMessengerBot(address, 0n)
+ await addMessengerBotTx.wait()
+ return addMessengerBotTx
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ },
+ [account, accountWriteContract],
+ )
+
+ const removeMessengerBot = useCallback(
+ async address => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+ try {
+ const removeMessengerBotTx = await accountWriteContract.removeMessengerBot(address)
+ await removeMessengerBotTx.wait()
+ return removeMessengerBotTx
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ },
+ [account, accountWriteContract],
+ )
+
+ const addWantedServices = useCallback(
+ async services => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+ try {
+ const wantedServicesTx = await accountWriteContract.addWantedServices(services)
+ await wantedServicesTx.wait()
+ return wantedServicesTx
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ },
+ [account, accountWriteContract],
+ )
+ const removeWantedServices = useCallback(
+ async services => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+ try {
+ const wantedServicesTx = await accountWriteContract.removeWantedServices(services)
+ await wantedServicesTx.wait()
+ return wantedServicesTx
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ },
+ [account, writeToContract],
+ )
+
+ const setOffChainPaymentSupported = useCallback(
+ async value => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+ try {
+ const tx = await accountWriteContract.setOffChainPaymentSupported(value)
+ return tx
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ },
+ [account, accountWriteContract],
+ )
+
+ const getOffChainPaymentSupported = useCallback(async () => {
+ if (!account) {
+ console.error('Account is not initialized')
+ return
+ }
+ try {
+ const offChainPaymentSupported = await readFromContract(
+ 'account',
+ 'offChainPaymentSupported',
+ )
+ return offChainPaymentSupported
+ } catch (error) {
+ console.error(error)
+ throw error
+ }
+ }, [account, readFromContract])
+
+ return {
+ CreateConfiguration,
+ account,
+ removeWantedServices,
+ getOffChainPaymentSupported,
+ setOffChainPaymentSupported,
+ getWantedServices,
+ addWantedServices,
+ getSupportedServices,
+ addServices,
+ removeServices,
+ getAllServices,
+ isCMAccount,
+ addMessengerBot,
+ getListOfBots,
+ removeMessengerBot,
+ }
+}
diff --git a/src/helpers/useSmartContract.tsx b/src/helpers/useSmartContract.tsx
new file mode 100644
index 00000000..eb7b19ab
--- /dev/null
+++ b/src/helpers/useSmartContract.tsx
@@ -0,0 +1,179 @@
+import { ethers } from 'ethers'
+import React, { createContext, ReactNode, useContext, useEffect, useState } from 'react'
+import store from 'wallet/store'
+import { useAppSelector } from '../hooks/reduxHooks'
+import { getActiveNetwork } from '../redux/slices/network'
+import CMAccount from './CMAccountManagerModule#CMAccount.json'
+import CMAccountManager from './ManagerProxyModule#CMAccountManager.json'
+
+const SmartContractContext = createContext(null)
+
+export const useSmartContract = () => useContext(SmartContractContext)
+
+type SmartContractProviderProps = {
+ children?: ReactNode
+}
+
+export const SmartContractProvider: React.FC = ({ children }) => {
+ const [provider, setProvider] = useState(null)
+ const [managerReadContract, setManagerReadContract] = useState(null)
+ const [managerWriteContract, setManagerWriteContract] = useState(null)
+ const [accountReadContract, setAccountReadContract] = useState(null)
+ const [accountWriteContract, setAccountWriteContract] = useState(null)
+ const [wallet, setWallet] = useState(null)
+ const [account, setAccount] = useState(null)
+ const [contractCMAccountAddress, setContractCMAccountAddress] = useState('')
+ const auth = useAppSelector(state => state.appConfig.isAuth)
+ const contractCMAccountManagerAddress = '0xE5B2f76C778D082b07BDd7D51FFe83E3E055B47F'
+
+ const CMAccountCreated = async (state, cmAccountAddress) => {
+ const accountWritableContract = new ethers.Contract(cmAccountAddress, CMAccount, wallet)
+ const accountReadOnlyContract = new ethers.Contract(cmAccountAddress, CMAccount, provider)
+ setContractCMAccountAddress(cmAccountAddress)
+ setAccountReadContract(accountReadOnlyContract)
+ setAccountWriteContract(accountWritableContract)
+ if (!account) {
+ console.error('Account is not initialized')
+ return { success: false, error: 'Account is not initialized' }
+ }
+ try {
+ for (const service of state.services) {
+ const tx = await accountWritableContract.addService(
+ service.name,
+ parseInt(service.fee),
+ service.rackRates,
+ service.capabilities,
+ )
+ const receipt = await tx.wait()
+ }
+
+ if (state.wantedServices.length > 0) {
+ const wantedServicesTx = await accountWritableContract.addWantedServices(
+ state.wantedServices,
+ )
+ await wantedServicesTx.wait()
+ }
+
+ const offChainPaymentTx = await accountWritableContract.setOffChainPaymentSupported(
+ state.isOffChainPayement,
+ )
+ await offChainPaymentTx.wait()
+
+ return { success: true, message: 'All operations completed successfully' }
+ } catch (error) {
+ console.error('Error in CMAccountCreated:', error)
+ return { success: false, error: error.message }
+ }
+ }
+
+ const initializeCMAccountContract = async () => {
+ if (!provider) return
+ try {
+ const accountWritableContract = new ethers.Contract(
+ contractCMAccountAddress,
+ CMAccount,
+ wallet,
+ )
+ const accountReadOnlyContract = new ethers.Contract(
+ contractCMAccountAddress,
+ CMAccount,
+ provider,
+ )
+ setAccountReadContract(accountReadOnlyContract)
+ setAccountWriteContract(accountWritableContract)
+ } catch (error) {
+ console.error('User denied account access:', error)
+ }
+ }
+ const initializeEthers = async () => {
+ const selectedNetwork = store.getters['Network/selectedNetwork']
+ const ethersProvider = new ethers.JsonRpcProvider(
+ `${selectedNetwork.protocol}://${selectedNetwork.ip}:${selectedNetwork.port}/ext/bc/C/rpc`,
+ )
+ try {
+ const wallet = new ethers.Wallet(store.state.activeWallet?.ethKey, ethersProvider)
+ const managerWritableContract = new ethers.Contract(
+ contractCMAccountManagerAddress,
+ CMAccountManager.abi,
+ wallet,
+ )
+ const managerReadOnlyContract = new ethers.Contract(
+ contractCMAccountManagerAddress,
+ CMAccountManager.abi,
+ ethersProvider,
+ )
+ setWallet(wallet)
+ setProvider(ethersProvider)
+ setManagerReadContract(managerReadOnlyContract)
+ setManagerWriteContract(managerWritableContract)
+ setAccount(wallet.address)
+ } catch (error) {
+ console.error('User denied account access:', error)
+ }
+ }
+ const activeNetwork = useAppSelector(getActiveNetwork)
+
+ useEffect(() => {
+ if (auth) initializeEthers()
+ }, [activeNetwork, auth])
+
+ useEffect(() => {
+ if (contractCMAccountAddress) initializeCMAccountContract()
+ }, [provider, contractCMAccountAddress])
+
+ const readFromContract = async (
+ contractType: 'manager' | 'account',
+ method: string,
+ ...args: any[]
+ ) => {
+ const contract = contractType === 'manager' ? managerReadContract : accountReadContract
+ if (!contract) {
+ return
+ }
+
+ try {
+ const result = await contract[method](...args)
+ return result
+ } catch (error) {
+ console.error(`Error reading from ${contractType} contract (method: ${method}):`, error)
+ throw error
+ }
+ }
+
+ const writeToContract = async (
+ contractType: 'manager' | 'account',
+ method: string,
+ ...args: any[]
+ ) => {
+ const contract = contractType === 'manager' ? managerWriteContract : accountWriteContract
+ if (!contract) {
+ return
+ }
+
+ try {
+ const tx = await contract[method](...args)
+ const receipt = await tx.wait()
+ return receipt
+ } catch (error) {
+ console.error(`Error writing to ${contractType} contract (method: ${method}):`, error)
+ throw error
+ }
+ }
+
+ const value = {
+ contractCMAccountAddress,
+ setContractCMAccountAddress,
+ wallet,
+ provider,
+ managerReadContract,
+ managerWriteContract,
+ accountReadContract,
+ accountWriteContract,
+ account,
+ readFromContract,
+ writeToContract,
+ CMAccountCreated,
+ }
+
+ return {children}
+}
diff --git a/src/helpers/useWalletBalance.tsx b/src/helpers/useWalletBalance.tsx
new file mode 100644
index 00000000..80fd289c
--- /dev/null
+++ b/src/helpers/useWalletBalance.tsx
@@ -0,0 +1,38 @@
+import { ethers } from 'ethers'
+import { useEffect, useState } from 'react'
+import store from 'wallet/store'
+import { useSmartContract } from './useSmartContract'
+const useWalletBalance = () => {
+ const [balance, setBalance] = useState('')
+ const [balanceOfAnAddress, setBalanceOfAnAddress] = useState('')
+ const [error, setError] = useState(null)
+ const { provider } = useSmartContract()
+
+ async function getBalanceOfAnAddress(address: string) {
+ const fetchedBalance = await provider.getBalance(address)
+ setBalanceOfAnAddress(ethers.formatEther(fetchedBalance))
+ }
+ useEffect(() => {
+ const fetchBalance = async () => {
+ if (!provider) {
+ setBalance(null)
+ return
+ }
+
+ try {
+ const fetchedBalance = await provider.getBalance(
+ '0x' + store.state.activeWallet.ethAddress,
+ )
+ setBalance(ethers.formatEther(fetchedBalance))
+ } catch (err) {
+ console.error('Error fetching balance:', err)
+ setError(err.message)
+ }
+ }
+
+ fetchBalance()
+ }, [provider])
+ return { balance, error, balanceOfAnAddress, getBalanceOfAnAddress }
+}
+
+export default useWalletBalance
diff --git a/src/layout/PartnersLayout.tsx b/src/layout/PartnersLayout.tsx
index 467a7c32..de69b03f 100644
--- a/src/layout/PartnersLayout.tsx
+++ b/src/layout/PartnersLayout.tsx
@@ -1,51 +1,131 @@
-import { Box, Toolbar } from '@mui/material'
+import { Box, Toolbar, Typography } from '@mui/material'
-import React from 'react'
-import { Outlet } from 'react-router'
+import React, { useEffect } from 'react'
+import { Navigate, Outlet, useNavigate } from 'react-router'
+import store from 'wallet/store'
+import { PartnerConfigurationProvider } from '../helpers/partnerConfigurationContext'
+import { SmartContractProvider } from '../helpers/useSmartContract'
+import { useAppSelector } from '../hooks/reduxHooks'
+import { useIsPartnerQuery } from '../redux/services/partners'
+import { getWalletName } from '../redux/slices/app-config'
import Links from '../views/settings/Links'
-const PartnersLayout = () => {
+const ClaimProfile = () => {
return (
- theme.palette.background.paper,
- flexGrow: 1,
- p: '1.5rem',
- zIndex: 9,
- position: 'fixed',
- top: '65px',
- width: '100vw',
- height: '61px',
- display: 'flex',
- justifyContent: 'center',
- right: 0,
- }}
- >
-
-
- theme.customWidth.layoutMaxWitdh,
- }}
- >
-
-
+ Claim a profile
+
+ Get in touch with the Camino Foundation to claim a Partner page and be then be able
+ to edit it and to create/manage a Camino Messenger configuration
+
)
}
+const PartnersLayout = () => {
+ const path = window.location.pathname
+ const { data, isLoading } = useIsPartnerQuery({
+ pChainAddress: 'P-camino1avxc8uyqzf9hzwa9eacgg2x8y473j85sd2jwdt',
+ })
+ const walletName = useAppSelector(getWalletName)
+ const navigate = useNavigate()
+ useEffect(() => {
+ if (
+ walletName &&
+ path.includes('partners/messenger-configuration') &&
+ store.state.activeWallet?.type === 'multisig'
+ ) {
+ navigate('/')
+ }
+ }, [walletName])
+ if (isLoading) return <>>
+ if (path.includes('partners/messenger-configuration') && !store.state.isAuth) {
+ return
+ }
+ return (
+
+
+
+ theme.palette.background.paper,
+ flexGrow: 1,
+ p: '1.5rem',
+ zIndex: 9,
+ position: 'fixed',
+ top: '65px',
+ width: '100vw',
+ height: '61px',
+ display: 'flex',
+ justifyContent: 'center',
+ right: 0,
+ }}
+ >
+
+
+ {path.includes('partners/messenger-configuration') && !!data && (
+ theme.palette.background.paper,
+ flexGrow: 1,
+ p: '1.5rem',
+ zIndex: 9,
+ position: 'fixed',
+ top: '129px',
+ width: '100vw',
+ height: '61px',
+ display: 'flex',
+ justifyContent: 'center',
+ right: 0,
+ }}
+ >
+
+
+ )}
+ theme.customWidth.layoutMaxWitdh,
+ mb: '2rem',
+ }}
+ >
+ {!path.includes('partners/messenger-configuration') ||
+ (path.includes('partners/messenger-configuration') && !!data) ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ )
+}
+
export default PartnersLayout
diff --git a/src/layout/RoutesSuite.tsx b/src/layout/RoutesSuite.tsx
index 575e5086..f9eb1f11 100644
--- a/src/layout/RoutesSuite.tsx
+++ b/src/layout/RoutesSuite.tsx
@@ -13,8 +13,12 @@ import ExplorerApp from '../views/explorer/ExplorerApp'
import LandingPage from '../views/landing/LandingPage'
import LoginPage from '../views/login/LoginPage'
import Partners from '../views/partners'
+import ConfigurDistrubitor from '../views/partners/ConfigurDistrubitor'
+import ConfigurSupplier from '../views/partners/ConfigurSupplier'
+import Overreview from '../views/partners/Configuration'
import CreatedOffers from '../views/partners/CreatedOffers'
import Foundation from '../views/partners/Foundation'
+import ManageBots from '../views/partners/ManageBots'
import Partner from '../views/partners/Partner'
import MultisigWallet from '../views/settings/MultisigWallet'
import VerifyWallet from '../views/settings/VerifyWallet'
@@ -110,7 +114,15 @@ export default function RoutesSuite() {
}>
} />
}>
+
+ } />
+ } />
+ } />
+ } />
+ } />
+
+ }>
} />
} />
}>
diff --git a/src/redux/services/partners.ts b/src/redux/services/partners.ts
index 50a9de24..d19509f6 100644
--- a/src/redux/services/partners.ts
+++ b/src/redux/services/partners.ts
@@ -45,7 +45,18 @@ export const partnersApi = createApi({
return response.data[0]
},
}),
+ isPartner: build.query({
+ query: ({ pChainAddress }) => {
+ let query =
+ '?populate=*&sort[0]=companyName:asc&pagination[page]=1&pagination[pageSize]=12'
+ query += `&filters[pChainAddress][$contains]=${pChainAddress}`
+ return query
+ },
+ transformResponse: (response: PartnersResponseType) => {
+ return response.data[0]
+ },
+ }),
}),
})
-export const { useListPartnersQuery, useFetchPartnerDataQuery } = partnersApi
+export const { useListPartnersQuery, useFetchPartnerDataQuery, useIsPartnerQuery } = partnersApi
diff --git a/src/redux/store.ts b/src/redux/store.ts
index 421f2315..30f562c2 100644
--- a/src/redux/store.ts
+++ b/src/redux/store.ts
@@ -1,8 +1,8 @@
-import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit'
+import { Action, configureStore, ThunkAction } from '@reduxjs/toolkit'
+import { partnersApi } from './services/partners'
import appConfigReducer from './slices/app-config'
-import themeReducer from './slices/theme'
import network from './slices/network'
-import { partnersApi } from './services/partners'
+import themeReducer from './slices/theme'
export type AppDispatch = typeof store.dispatch
export type RootState = ReturnType
export type AppThunk = ThunkAction<
diff --git a/src/views/partners/ConfigurDistrubitor.tsx b/src/views/partners/ConfigurDistrubitor.tsx
new file mode 100644
index 00000000..48ed588d
--- /dev/null
+++ b/src/views/partners/ConfigurDistrubitor.tsx
@@ -0,0 +1,231 @@
+import { Box, Divider, FormControl, MenuItem, Select, Typography } from '@mui/material'
+import React, { useEffect, useReducer, useState } from 'react'
+import MainButton from '../../components/MainButton'
+import {
+ actionTypes,
+ reducer,
+ usePartnerConfigurationContext,
+} from '../../helpers/partnerConfigurationContext'
+import { usePartnerConfig } from '../../helpers/usePartnerConfig'
+import { Configuration } from './Configuration'
+
+const ConfigurDistrubitor = () => {
+ const { removeWantedServices, addWantedServices, getWantedServices } = usePartnerConfig()
+ const { state, dispatch } = usePartnerConfigurationContext()
+ const [distrubitorState, dispatchDistrubitorState] = useReducer(reducer, { ...state, step: 2 })
+ const [editing, setEditing] = useState(false)
+ const [loading, setLoading] = useState(false)
+
+ const handleChange = event => {
+ addService(event.target.value)
+ }
+ const addService = service => {
+ if (
+ !distrubitorState.stepsConfig[distrubitorState.step].services.find(
+ elem => elem.name === service,
+ )
+ )
+ dispatchDistrubitorState({
+ type: actionTypes.ADD_SERVICE,
+ payload: {
+ step: distrubitorState.step,
+ newService: {
+ name: distrubitorState.registredServices.find(elem => elem === service),
+ fee: '0',
+ capabilities: [''],
+ rackRates: true,
+ },
+ },
+ })
+ }
+
+ async function confirmEditing() {
+ setLoading(true)
+ const originalNames = new Set(state.stepsConfig[2].services.map(item => item.name))
+ const updatedNames = new Set(
+ distrubitorState.stepsConfig[2].services.map(item => item.name),
+ )
+
+ const removed = state.stepsConfig[2].services.filter(item => !updatedNames.has(item.name))
+ const added = distrubitorState.stepsConfig[2].services.filter(
+ item => !originalNames.has(item.name),
+ )
+ await removeWantedServices(removed.map(elem => elem.name))
+ await addWantedServices(added.map(elem => elem.name))
+ let res = await getWantedServices()
+ dispatch({
+ type: actionTypes.UPDATE_WANTED_SERVICES,
+ payload: { wantedServices: res },
+ })
+ setLoading(false)
+ setEditing(false)
+ console.log({
+ removed,
+ added,
+ })
+ }
+
+ function cancelEditing() {
+ dispatchDistrubitorState({
+ type: actionTypes.RESET_STATE,
+ payload: { initialState: { ...state, step: 2 } },
+ })
+ console.log({ state: distrubitorState.stepsConfig[2].services })
+ setEditing(false)
+ }
+ useEffect(() => {
+ dispatchDistrubitorState({
+ type: actionTypes.RESET_STATE,
+ payload: { initialState: { ...state, step: 2 } },
+ })
+ }, [state])
+ return (
+
+
+ Wanted Services
+ {state.stepsConfig[2].paragraph && (
+
+ {state.stepsConfig[2].paragraph}
+
+ )}
+
+
+ services
+
+
+
+
+
+
+
+
+
+ {!editing ? (
+ {
+ setEditing(true)
+ }}
+ >
+ Edit configuration
+
+ ) : (
+ <>
+ {
+ cancelEditing()
+ }}
+ >
+ Cancel Editing
+
+ {
+ confirmEditing()
+ }}
+ >
+ Confirm Editing
+
+ >
+ )}
+
+
+
+
+
+
+ )
+}
+
+export default ConfigurDistrubitor
diff --git a/src/views/partners/ConfigurSupplier.tsx b/src/views/partners/ConfigurSupplier.tsx
new file mode 100644
index 00000000..96a91c03
--- /dev/null
+++ b/src/views/partners/ConfigurSupplier.tsx
@@ -0,0 +1,238 @@
+import { Box, Divider, FormControl, MenuItem, Select, Typography } from '@mui/material'
+import React, { useEffect, useReducer, useState } from 'react'
+import MainButton from '../../components/MainButton'
+import {
+ actionTypes,
+ reducer,
+ usePartnerConfigurationContext,
+} from '../../helpers/partnerConfigurationContext'
+import { usePartnerConfig } from '../../helpers/usePartnerConfig'
+import { Configuration } from './Configuration'
+
+const ConfigurSupplier = () => {
+ const { state, dispatch } = usePartnerConfigurationContext()
+ const [supplierState, dispatchSupplierState] = useReducer(reducer, { ...state, step: 1 })
+ const [editing, setEditing] = useState(false)
+ const [loading, setLoading] = useState(false)
+ const { removeServices, addServices, getSupportedServices } = usePartnerConfig()
+ const handleChange = event => {
+ addService(event.target.value)
+ }
+ const addService = service => {
+ if (
+ !supplierState.stepsConfig[supplierState.step].services.find(
+ elem => elem.name === service,
+ )
+ )
+ dispatchSupplierState({
+ type: actionTypes.ADD_SERVICE,
+ payload: {
+ step: supplierState.step,
+ newService: {
+ name: supplierState.registredServices.find(elem => elem === service),
+ fee: '0',
+ capabilities: [''],
+ rackRates: true,
+ },
+ },
+ })
+ }
+ const isEqual = (a, b) => {
+ return (
+ a.name === b.name &&
+ a.fee === b.fee &&
+ a.rackRates === b.rackRates &&
+ JSON.stringify(a.capabilities) === JSON.stringify(b.capabilities)
+ )
+ }
+ async function confirmEditing() {
+ setLoading(true)
+ const removed = state.stepsConfig[supplierState.step].services.filter(
+ origItem =>
+ !supplierState.stepsConfig[supplierState.step].services.some(updatedItem =>
+ isEqual(origItem, updatedItem),
+ ),
+ )
+
+ const added = supplierState.stepsConfig[supplierState.step].services.filter(
+ updatedItem =>
+ !state.stepsConfig[supplierState.step].services.some(origItem =>
+ isEqual(origItem, updatedItem),
+ ),
+ )
+ await removeServices(removed)
+ await addServices(added)
+ let res = await getSupportedServices()
+ dispatch({
+ type: actionTypes.UPDATE_SUPPORTED_SERVICES,
+ payload: { services: res },
+ })
+ setLoading(false)
+ setEditing(false)
+ }
+
+ function cancelEditing() {
+ dispatchSupplierState({
+ type: actionTypes.RESET_STATE,
+ payload: { initialState: { ...state, step: 1 } },
+ })
+ setEditing(false)
+ }
+
+ useEffect(() => {
+ dispatchSupplierState({
+ type: actionTypes.RESET_STATE,
+ payload: { initialState: { ...state, step: 1 } },
+ })
+ }, [state])
+
+ return (
+
+
+ Offered Services
+ {state.stepsConfig[1].paragraph && (
+
+ {state.stepsConfig[1].paragraph}
+
+ )}
+
+
+ services
+
+
+
+
+
+
+
+
+
+ {!editing ? (
+ {
+ setEditing(true)
+ }}
+ >
+ Edit configuration
+
+ ) : (
+ <>
+ {
+ cancelEditing()
+ }}
+ >
+ Cancel Editing
+
+ {
+ confirmEditing()
+ }}
+ >
+ Confirm Editing
+
+ >
+ )}
+
+
+
+
+
+
+ )
+}
+
+export default ConfigurSupplier
diff --git a/src/views/partners/Configuration.tsx b/src/views/partners/Configuration.tsx
new file mode 100644
index 00000000..fb5e4480
--- /dev/null
+++ b/src/views/partners/Configuration.tsx
@@ -0,0 +1,939 @@
+import { ContentCopy, RefreshOutlined } from '@mui/icons-material'
+import {
+ Box,
+ Button,
+ Checkbox,
+ Divider,
+ FormControl,
+ FormControlLabel,
+ InputAdornment,
+ MenuItem,
+ Select,
+ TextField,
+ Typography,
+} from '@mui/material'
+import React, { useEffect, useState } from 'react'
+import store from 'wallet/store'
+import Alert from '../../components/Alert'
+import Input from '../../components/Input'
+import MainButton from '../../components/MainButton'
+import {
+ actionTypes,
+ usePartnerConfigurationContext,
+} from '../../helpers/partnerConfigurationContext'
+import { usePartnerConfig } from '../../helpers/usePartnerConfig'
+import { useSmartContract } from '../../helpers/useSmartContract'
+import useWalletBalance from '../../helpers/useWalletBalance'
+
+const Content = () => {
+ const { contractCMAccountAddress } = useSmartContract()
+ const { state, dispatch } = usePartnerConfigurationContext()
+ const [loading, setLoading] = useState(false)
+ const handleChange = event => {
+ addService(event.target.value)
+ }
+ const partnerConfig = usePartnerConfig()
+ const nextStep = () => {
+ if (state.step < state.stepsConfig.length - 1)
+ dispatch({ type: actionTypes.UPDATE_STEP, payload: { step: state.step + 1 } })
+ }
+ const prevStep = () => {
+ if (state.step > 0)
+ dispatch({ type: actionTypes.UPDATE_STEP, payload: { step: state.step - 1 } })
+ }
+ const addService = service => {
+ if (!state.stepsConfig[state.step].services.find(elem => elem.name === service))
+ dispatch({
+ type: actionTypes.ADD_SERVICE,
+ payload: {
+ step: state.step,
+ newService: {
+ name: state.registredServices.find(elem => elem === service),
+ fee: '0',
+ capabilities: [''],
+ rackRates: true,
+ },
+ },
+ })
+ }
+
+ async function submit() {
+ setLoading(true)
+ await partnerConfig.CreateConfiguration(state)
+ setLoading(false)
+ }
+
+ const { balance, getBalanceOfAnAddress, balanceOfAnAddress } = useWalletBalance()
+ useEffect(() => {
+ if (contractCMAccountAddress) getBalanceOfAnAddress(contractCMAccountAddress)
+ }, [contractCMAccountAddress])
+ if (contractCMAccountAddress)
+ return (
+ <>
+
+
+ Messenger setup
+ Add funds to CM address
+
+ First you need to top up the CM Account with CAM, EURSH or USDC to work
+ properly. Transfer it to the newly generated CM address below.
+
+ theme.palette.text.primary,
+ WebkitTextFillColor: theme => theme.palette.text.primary,
+ },
+ },
+ endAdornment: (
+
+ `${theme.palette.text.primary} !important`,
+ }}
+ />
+ }
+ variant="outlined"
+ onClick={() => {
+ navigator.clipboard.writeText(contractCMAccountAddress)
+ }}
+ >
+ Copy
+
+ ),
+ }}
+ />
+
+ When the necessary balance has arrived you can continue to the next
+ step.
+
+
+ theme.palette.text.primary,
+ WebkitTextFillColor: theme => theme.palette.text.primary,
+ },
+ },
+ startAdornment: (
+ theme.palette.text.primary,
+ }}
+ >
+ CM Balance:
+
+ ),
+ endAdornment: (
+
+ {balanceOfAnAddress < 100 ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+ `${theme.palette.text.primary} !important`,
+ }}
+ />
+ }
+ variant="outlined"
+ onClick={() => {
+ getBalanceOfAnAddress(contractCMAccountAddress)
+ }}
+ >
+ Refresh
+
+
+ ),
+ }}
+ />
+ {balanceOfAnAddress !== '' && parseFloat(balanceOfAnAddress) < 100 && (
+
+ )}
+
+ Min. 100 CAM / 50 EURSH / 100.30 USDC
+
+
+
+
+
+
+ >
+ )
+ return (
+
+
+ Messenger setup
+ {state.stepsConfig[state.step].title}
+ {state.stepsConfig[state.step].paragraph && (
+
+ {state.stepsConfig[state.step].paragraph}
+
+ )}
+ {state.step === 0 && (
+ <>
+
+ {balance !== '' && parseFloat(balance) < 100 && (
+
+ )}
+ {!store.getters['Accounts/kycStatus'] && (
+
+ )}
+ >
+ )}
+ {(state.step === 1 || state.step === 2) && (
+
+
+ Are you a {state.stepsConfig[state.step].type}?
+
+ }
+ control={
+ theme.palette.secondary.main,
+ '&.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ '&.MuiCheckbox-colorSecondary.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ }}
+ checked={
+ state.step === 1
+ ? state.stepsConfig[state.step].isSupplier
+ : state.stepsConfig[state.step].isDistributor
+ }
+ onChange={() =>
+ dispatch({ type: actionTypes.UPDATE_IS_SUPPLIER })
+ }
+ />
+ }
+ />
+ {((state.step === 1 && state.stepsConfig[state.step].isSupplier) ||
+ (state.step === 2 && state.stepsConfig[state.step].isDistributor)) && (
+ <>
+
+ services
+
+
+
+
+
+ >
+ )}
+
+ )}
+ {state.step === 3 && (
+ <>
+ Offchain}
+ control={
+ theme.palette.secondary.main,
+ '&.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ '&.MuiCheckbox-colorSecondary.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ p: '0 8px',
+ }}
+ checked={state.stepsConfig[state.step].isOffChain}
+ onChange={() =>
+ dispatch({ type: actionTypes.UPDATE_IS_OFF_CHAIN })
+ }
+ />
+ }
+ />
+ CAM}
+ control={
+ theme.palette.secondary.main,
+ '&.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ '&.MuiCheckbox-colorSecondary.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ p: '0 8px',
+ }}
+ checked={state.stepsConfig[state.step].isCam}
+ onChange={() => dispatch({ type: actionTypes.UPDATE_IS_CAM })}
+ />
+ }
+ />
+ USDC* (coming soon) }
+ disabled
+ control={
+ theme.palette.secondary.main,
+ '&.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ '&.MuiCheckbox-colorSecondary.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ p: '0 8px',
+ }}
+ checked={state.stepsConfig[state.step].isCam}
+ onChange={() => dispatch({ type: actionTypes.UPDATE_IS_CAM })}
+ />
+ }
+ />
+ EURC* (coming soon)}
+ control={
+ theme.palette.secondary.main,
+ '&.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ '&.MuiCheckbox-colorSecondary.Mui-checked': {
+ color: theme => theme.palette.secondary.main,
+ },
+ p: '0 8px',
+ }}
+ checked={state.stepsConfig[state.step].isCam}
+ onChange={() => dispatch({ type: actionTypes.UPDATE_IS_CAM })}
+ />
+ }
+ />
+ >
+ )}
+ {state.step === 4 && (
+
+ {(state.stepsConfig[3].isOffChain || state.stepsConfig[3].isCam) && (
+
+ Payment methods
+ {state.stepsConfig[3].isOffChain && !state.stepsConfig[3].isCam && (
+ Offchain
+ )}
+ {!state.stepsConfig[3].isOffChain && state.stepsConfig[3].isCam && (
+ CAM
+ )}
+ {state.stepsConfig[3].isOffChain && state.stepsConfig[3].isCam && (
+ Offchain, CAM
+ )}
+
+ )}
+ {state.stepsConfig[1].isSupplier && (
+
+
+ Type
+ Supplier
+
+ {state.stepsConfig[1].services.map((elem, index) => {
+ return (
+
+ {elem.name}
+
+ Fee:
+ {elem.fee + (elem.rackRates ? ', Rack Rates' : '')}
+
+ {!elem.capabilities.filter(str => str.trim() !== '')
+ .length ? (
+
+ Capabilities: No Capabilities
+
+ ) : (
+ elem.capabilities
+ .filter(str => str.trim() !== '')
+ .map((capability, cp) => {
+ return capability ? (
+
+ Capability: {capability}
+
+ ) : null
+ })
+ )}
+
+ )
+ })}
+
+ )}
+ {state.stepsConfig[2].isDistributor && (
+
+
+ Type
+ Distributor
+
+ {state.stepsConfig[2].services.map((elem, index) => {
+ return (
+
+ {elem.name}
+
+ )
+ })}
+
+ )}
+
+ )}
+
+
+
+ Previous Step
+
+ {(state.step === 1 && !state.stepsConfig[state.step].isSupplier) ||
+ (state.step === 2 && !state.stepsConfig[state.step].isDistributor) ? (
+
+ Skip this step
+
+ ) : state.step !== 4 ? (
+
+ Next Step
+
+ ) : (
+
+ Create Configuration
+
+ )}
+
+
+
+ {state.step === 0 && (
+
+ )}
+
+
+
+ )
+}
+
+export function Configuration({ children, ...restProps }) {
+ return (
+
+ {children}
+
+ )
+}
+
+Configuration.SubTitle = function SubTitle({ children }) {
+ return (
+
+ {children}
+
+ )
+}
+
+Configuration.Title = function Title({ children }) {
+ return (
+
+ {children}
+
+ )
+}
+
+Configuration.Paragraphe = function Paragraphe({ children }) {
+ return {children}
+}
+
+Configuration.Buttons = function Buttons({ children }) {
+ return {children}
+}
+
+Configuration.Services = function Services({
+ state,
+ dispatch,
+ disabled,
+}: {
+ state: any
+ dispatch: any
+ disabled?: boolean
+}) {
+ const removeService = serviceIndex => {
+ dispatch({
+ type: actionTypes.REMOVE_SERVICE,
+ payload: {
+ step: state.step,
+ serviceIndex,
+ },
+ })
+ }
+
+ const addCapability = serviceIndex => {
+ dispatch({
+ type: actionTypes.ADD_CAPABILITIES,
+ payload: {
+ step: state.step,
+ serviceIndex,
+ },
+ })
+ }
+
+ const handleCapabilityChange = (event, serviceIndex, capabilityIndex) => {
+ dispatch({
+ type: actionTypes.UPDATE_CAPABILITY,
+ payload: {
+ step: state.step,
+ serviceIndex: serviceIndex,
+ capabilityIndex: capabilityIndex,
+ newValue: event.target.value,
+ },
+ })
+ }
+
+ const handleFeeChange = (event, serviceIndex) => {
+ dispatch({
+ type: actionTypes.UPDATE_FEE,
+ payload: {
+ step: state.step,
+ serviceIndex: serviceIndex,
+ newValue: event.target.value,
+ },
+ })
+ }
+
+ return (
+
+ {state.stepsConfig[state.step].services.map((service, index) => (
+
+ theme.palette.mode === 'dark' ? '#0F182A' : '#F1F5F9',
+ }}
+ >
+
+ {service.name}
+
+ {state.step === 1 && (
+
+ )}
+
+
+
+ {state.step === 1 && (
+ <>
+
+
+ FEE
+
+
+ handleFeeChange(e, index)}
+ sx={{
+ flex: '1',
+ '& .MuiInputBase-root': {
+ height: '40px',
+ },
+ '& input': {
+ fontSize: '14px',
+ height: '100%',
+ padding: '8px 14px',
+ },
+ }}
+ type="number"
+ InputProps={{
+ sx: {
+ '& input': {
+ fontSize: '14px',
+ },
+ },
+ }}
+ />
+ Rack Rates
+ }
+ control={
+ theme.palette.secondary.main,
+ '&.Mui-checked': {
+ color: theme =>
+ theme.palette.secondary.main,
+ },
+ '&.MuiCheckbox-colorSecondary.Mui-checked': {
+ color: theme =>
+ theme.palette.secondary.main,
+ },
+ }}
+ checked={
+ state.stepsConfig[state.step].services[index]
+ .rackRates
+ }
+ onChange={() =>
+ dispatch({
+ type: actionTypes.UPDATE_RACK_RATES,
+ payload: {
+ step: state.step,
+ serviceIndex: index,
+ },
+ })
+ }
+ />
+ }
+ />
+
+
+
+
+
+ {state.stepsConfig[state.step].services[index].capabilities.map(
+ (elem, key) => {
+ return (
+
+
+ Capabilities
+
+
+ handleCapabilityChange(e, index, key)
+ }
+ sx={{
+ flex: '1',
+ '& .MuiInputBase-root': {
+ height: '40px',
+ },
+ '& input': {
+ fontSize: '14px',
+ height: '100%',
+ padding: '8px 14px',
+ },
+ }}
+ type="string"
+ InputProps={{
+ sx: {
+ '& input': {
+ fontSize: '14px',
+ },
+ },
+ }}
+ placeholder="Describe your capabilities..."
+ />
+
+
+
+
+ )
+ },
+ )}
+ >
+ )}
+
+ ))}
+
+ )
+}
+
+Configuration.Infos = function Infos({ rackRates, information }) {
+ return (
+
+
+ information
+ {information}
+
+
+
+ rack rates
+ {rackRates}
+
+
+ )
+}
+
+const Overreview = () => {
+ return (
+ <>
+
+ >
+ )
+}
+export default Overreview
diff --git a/src/views/partners/ManageBots.tsx b/src/views/partners/ManageBots.tsx
new file mode 100644
index 00000000..ae1f501d
--- /dev/null
+++ b/src/views/partners/ManageBots.tsx
@@ -0,0 +1,246 @@
+import { Box, Button, CircularProgress, TextField, Typography } from '@mui/material'
+import { ethers } from 'ethers'
+import React, { useEffect, useState } from 'react'
+import Alert from '../../components/Alert'
+import { usePartnerConfig } from '../../helpers/usePartnerConfig'
+import { Configuration } from './Configuration'
+
+const ManageBots = () => {
+ const [isValidAddress, setIsValidAddress] = useState(false)
+ const [address, setAddress] = useState('')
+ const [bots, setBots] = useState([])
+ const [loading, setLoading] = useState(false)
+ const handleAddressChange = e => {
+ const newAddress = e.target.value
+ setAddress(newAddress)
+ setIsValidAddress(ethers.isAddress(newAddress))
+ }
+ const { addMessengerBot, getListOfBots, removeMessengerBot } = usePartnerConfig()
+
+ async function fetchBots() {
+ setLoading(true)
+ const res = await getListOfBots()
+ setLoading(false)
+ setBots(res)
+ }
+ useEffect(() => {
+ fetchBots()
+ }, [])
+ const handleAddBot = () => {
+ if (isValidAddress) {
+ setLoading(true)
+ addMessengerBot(address).then(() => {
+ setAddress('')
+ fetchBots()
+ })
+ }
+ }
+ const handleRemoveBot = address => {
+ setLoading(true)
+ removeMessengerBot(address).then(() => fetchBots())
+ }
+ return (
+
+
+ Manage Bots
+
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula
+ eget dolor. Aenean massa. Donec sociis natoque penatibus.
+
+ {loading && (
+
+
+
+ )}
+ {bots &&
+ bots.length > 0 &&
+ bots.map((bot, index) => {
+ return (
+
+
+
+ theme.palette.mode === 'dark'
+ ? '#0F182A'
+ : '#F1F5F9',
+ borderWidth: '1px',
+ '&:hover': {
+ borderWidth: '1px',
+ boxShadow: 'none',
+ },
+ }}
+ variant="caption"
+ >
+ Bot
+
+ theme.palette.text.primary,
+ WebkitTextFillColor: theme =>
+ theme.palette.text.primary,
+ },
+ },
+ }}
+ onChange={handleAddressChange}
+ />
+
+
+
+ )
+ })}
+
+
+
+ theme.palette.mode === 'dark' ? '#0F182A' : '#F1F5F9',
+ borderWidth: '1px',
+ '&:hover': {
+ borderWidth: '1px',
+ boxShadow: 'none',
+ },
+ }}
+ variant="caption"
+ >
+ Bot
+
+
+
+
+ {address !== '' && !isValidAddress && (
+
+ )}
+
+
+
+
+
+
+ )
+}
+
+export default ManageBots
diff --git a/src/views/settings/Links.tsx b/src/views/settings/Links.tsx
index ba5631d3..a4e0b117 100644
--- a/src/views/settings/Links.tsx
+++ b/src/views/settings/Links.tsx
@@ -4,7 +4,9 @@ import Box from '@mui/material/Box'
import Tab from '@mui/material/Tab'
import Tabs from '@mui/material/Tabs'
import { useNavigate } from 'react-router'
-import { useAppDispatch } from '../../hooks/reduxHooks'
+import store from 'wallet/store'
+import { useSmartContract } from '../../helpers/useSmartContract'
+import { useAppDispatch, useAppSelector } from '../../hooks/reduxHooks'
import { changeActiveApp } from '../../redux/slices/app-config'
function a11yProps(index: number) {
@@ -14,20 +16,31 @@ function a11yProps(index: number) {
}
}
-export default function Links() {
+export default function Links({ type = 'else' }: { type?: string }) {
const dispatch = useAppDispatch()
const [value, setValue] = useState(0)
+ const [secondValue, setSecondValue] = useState(0)
const navigate = useNavigate()
const path = window.location.pathname
- const handleChange = (event: React.SyntheticEvent, newValue: number) => setValue(newValue)
+ const handleChange = (event: React.SyntheticEvent, newValue: number) => {
+ if (type === 'subtabs') {
+ setSecondValue(newValue)
+ } else setValue(newValue)
+ }
useEffect(() => {
if (path === '/settings') setValue(0)
else if (path === '/settings/manage-multisig') setValue(1)
else if (path === '/settings/verify-wallet') setValue(2)
+ else if (path === '/partners') setValue(0)
+ else if (path.includes('partners/messenger-configuration')) setValue(1)
+ else if (path.includes('overview')) setSecondValue(0)
+ else if (path.includes('distribution')) setSecondValue(1)
+ else if (path.includes('supply')) setSecondValue(2)
else setValue(0)
dispatch(changeActiveApp('Network'))
}, [path]) // eslint-disable-line react-hooks/exhaustive-deps
-
+ const auth = useAppSelector(state => state.appConfig.isAuth)
+ const sc = useSmartContract()
const settingsTabs = [
navigate('/partners')}
className="tab"
disableRipple
label="Partner showroom"
@@ -67,21 +81,96 @@ export default function Links() {
key={0}
sx={{ '&::after': { display: value === 0 ? 'block' : 'none' } }}
/>,
+ auth && store.state.activeWallet?.type !== 'multisig' && (
+ navigate('/partners/messenger-configuration')}
+ className="tab"
+ disableRipple
+ label="My Partners Profile"
+ {...a11yProps(1)}
+ key={1}
+ sx={{ '&::after': { display: value === 1 ? 'block' : 'none' } }}
+ />
+ ),
+ ]
+
+ const partnersSubTabs = [
+ navigate('/partners/messenger-configuration/messenger')}
+ className="tab"
+ disableRipple
+ label="My Messenger Account"
+ {...a11yProps(0)}
+ key={0}
+ sx={{ '&::after': { display: secondValue === 0 ? 'block' : 'none' } }}
+ />,
+ navigate('/partners/messenger-configuration/supplier')}
+ className="tab"
+ disableRipple
+ label="Offered Services"
+ {...a11yProps(1)}
+ key={1}
+ sx={{ '&::after': { display: secondValue === 1 ? 'block' : 'none' } }}
+ />,
+ navigate('/partners/messenger-configuration/distribution')}
+ className="tab"
+ disableRipple
+ label="Wanted Services"
+ {...a11yProps(2)}
+ key={2}
+ sx={{ '&::after': { display: secondValue === 2 ? 'block' : 'none' } }}
+ />,
+ navigate('/partners/messenger-configuration/bots')}
+ className="tab"
+ disableRipple
+ label="Manage Bots"
+ {...a11yProps(3)}
+ key={3}
+ sx={{ '&::after': { display: secondValue === 3 ? 'block' : 'none' } }}
+ />,
]
+ if (type === 'subtabs')
+ return (
+
+
+ {partnersSubTabs.map((tab, index) => (tab ? tab : null))}
+
+
+ )
return (
- {path.includes('/partners')
- ? partnersTabs.map((tab, index) => (tab ? tab : null))
+ {type === 'subtabs'
+ ? partnersSubTabs.map((tab, index) => (tab ? tab : null))
+ : path.includes('/partners')
+ ? partnersTabs.map((tab, index) => {
+ return tab
+ })
: settingsTabs.map((tab, index) => (tab ? tab : null))}
diff --git a/tsconfig.json b/tsconfig.json
index 25236f17..c70fc070 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,15 @@
{
"compilerOptions": {
+ "target": "ES2020",
"jsx": "react",
- "esModuleInterop": true
+ "resolveJsonModule": true,
+ "moduleResolution": "node",
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "typeRoots": ["node_modules/@types"],
+ "paths": {
+ "ethers": ["./node_modules/ethers"]
+ }
},
"include": ["src"],
"ts-node": {
diff --git a/webpack.common.js b/webpack.common.js
index 25722f98..9a3744e1 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -36,6 +36,11 @@ module.exports = {
fullySpecified: false,
},
},
+ {
+ test: /\.json$/,
+ loader: 'json-loader',
+ type: 'javascript/auto',
+ },
{
test: /\.(css|s[ac]ss)$/i,
use: ['style-loader', 'css-loader', 'postcss-loader'],
diff --git a/webpack.dev.js b/webpack.dev.js
index 8384ced6..f655a06e 100644
--- a/webpack.dev.js
+++ b/webpack.dev.js
@@ -36,6 +36,11 @@ module.exports = merge(common, {
singleton: true,
requiredVersion: deps['react-dom'],
},
+ ethers: {
+ singleton: true,
+ eager: true,
+ requiredVersion: deps['ethers'],
+ },
},
}),
],