diff --git a/package.json b/package.json index ed54232..76bd581 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@blocto/fcl": "^1.0.0-alpha.1", - "@blocto/sdk": "0.4.3", + "@blocto/sdk": "^0.5.0", "@chakra-ui/icons": "^1.1.1", "@chakra-ui/react": "^1.7.4", "@emotion/react": "^11", diff --git a/src/components/AptosEditor.tsx b/src/components/AptosEditor.tsx index b4482bb..3ef71bd 100644 --- a/src/components/AptosEditor.tsx +++ b/src/components/AptosEditor.tsx @@ -14,6 +14,7 @@ import ScriptTypes, { PerInfo, PerScriptAbi, } from "../types/ScriptTypes"; +import type { AptosTypes } from "@blocto/sdk"; import Editor from "./Editor"; const typeKeys = Object.values(AptosArgTypes); @@ -36,7 +37,7 @@ const formatTransactionArgs = (args: Arg[] | undefined) => { : currentValue.value; } return initial; - }, {}); + }, {}) as AptosTypes.SignMessagePayload; }; const AptosEditor = (): ReactJSXElement => { @@ -55,7 +56,7 @@ const AptosEditor = (): ReactJSXElement => { }, []); const handleSignMessage = useCallback((args) => { - return new Promise((resolve) => { + return new Promise((resolve) => { const aptos = ChainServices[Chains.Aptos]?.bloctoSDK?.aptos; resolve(aptos.signMessage(formatTransactionArgs(args))); }); @@ -122,7 +123,7 @@ const AptosEditor = (): ReactJSXElement => { isTransactionsExtraSignersAvailable isSandboxDisabled defaultTab={ScriptTypes.CONTRACT} - disabledTabs={[ScriptTypes.TX]} + disabledTabs={[ScriptTypes.TX, ScriptTypes.USER_OPERATION]} tabsShouldLoadDefaultTemplate={[ ScriptTypes.SCRIPT, ScriptTypes.CONTRACT, diff --git a/src/components/Editor.tsx b/src/components/Editor.tsx index a905402..51e8076 100644 --- a/src/components/Editor.tsx +++ b/src/components/Editor.tsx @@ -55,6 +55,7 @@ const TabNames = [ "Contract", "Sign Message", "Resource", + "User Operations", ]; const isMainnet = process.env.REACT_APP_NETWORK === "mainnet"; @@ -65,10 +66,12 @@ interface EditorProps { shouldSign: boolean | undefined, signers: Array<{ privateKey: string; address: string }> | undefined, script: string, - method?: (...param: any[]) => Promise + method?: (...param: any[]) => Promise, + isUserOperation?: boolean ) => Promise<{ - transactionId: string; + transactionId?: string; transaction?: any; + userOpHash?: string; subscribeFunc?: (callback: (transaction: any) => void) => () => void; isSealed?: (transaction: any) => boolean; }>; @@ -214,7 +217,7 @@ const Editor: React.FC = ({ .catch((error) => { setError(error?.message || "Error: Signing message failed."); }); - } else if (scriptType === ScriptTypes.TX) { + } else if (scriptType === ScriptTypes.TX && onSendTransactions) { onSendTransactions( args, shouldSign, @@ -223,8 +226,39 @@ const Editor: React.FC = ({ methodRef.current ) .then(({ transactionId, transaction, subscribeFunc, isSealed }) => { - setTxHash(transactionId); - setResponse(transaction); + if (transactionId) { + setTxHash(transactionId); + setResponse(transaction); + } + + if (subscribeFunc && isSealed) { + const unsub = subscribeFunc((transaction: any) => { + setResponse(transaction); + if (isSealed(transaction)) { + unsub(); + } + }); + } + }) + .catch((error) => { + setError(error?.message || "Error: Sending transaction failed."); + }); + } else if ( + scriptType === ScriptTypes.USER_OPERATION && + onSendTransactions + ) { + onSendTransactions( + args, + shouldSign, + signers, + script, + methodRef.current, + true + ) + .then(({ userOpHash, subscribeFunc, isSealed }) => { + if (userOpHash) { + setResult(userOpHash); + } if (subscribeFunc && isSealed) { const unsub = subscribeFunc((transaction: any) => { diff --git a/src/components/EvmEditor.tsx b/src/components/EvmEditor.tsx index 2b1ede2..6a02b8c 100644 --- a/src/components/EvmEditor.tsx +++ b/src/components/EvmEditor.tsx @@ -5,6 +5,7 @@ import { Context } from "../context/Context"; import * as ContractTemplates from "../scripts/evm/Contract"; import * as SignMessageTemplates from "../scripts/evm/SignMessage"; import * as TransactionsTemplates from "../scripts/evm/Transactions"; +import * as UserOperationsTemplates from "../scripts/evm/UserOperations"; import { EvmChain } from "../types/ChainTypes"; import ScriptTypes, { Arg, ArgTypes, PerInfo } from "../types/ScriptTypes"; import Editor from "./Editor"; @@ -13,7 +14,7 @@ import EvmChainSelect from "./EvmChainSelect"; const typeKeys = Object.values(ArgTypes); const FaucetUrls = { - [EvmChain.Ethereum]: "https://rinkeby-faucet.com/", + [EvmChain.Ethereum]: "https://goerlifaucet.com/", [EvmChain.Bsc]: "https://testnet.binance.org/faucet-smart", [EvmChain.Polygon]: "https://faucet.polygon.technology/", [EvmChain.Avalanche]: "https://faucet.avax-test.network/", @@ -25,6 +26,7 @@ const MenuGroups = [ { title: "Transactions", templates: TransactionsTemplates }, { title: "Sign Message", templates: SignMessageTemplates }, { title: "Contract", templates: ContractTemplates }, + { title: "User Operations", templates: UserOperationsTemplates }, ]; const formatTransactionArgs = (args: Arg[] | undefined) => { @@ -99,8 +101,13 @@ const EvmEditor = (): ReactJSXElement => { shouldSign: boolean | undefined, signers: Array<{ privateKey: string; address: string }> | undefined, script: string, - method?: (...param: any[]) => Promise - ): Promise<{ transactionId: string; transaction: any }> => { + method?: (...param: any[]) => Promise, + isUserOperation?: boolean + ): Promise<{ + transactionId?: string; + transaction?: any; + userOpHash?: string; + }> => { return new Promise(async (resolve, reject) => { if (!method) { return reject(new Error("Error: Transaction method is missing.")); @@ -109,28 +116,48 @@ const EvmEditor = (): ReactJSXElement => { const address = await checkArgumentsAndAddress(args); const formattedArgs = formatTransactionArgs(args); - method(address, formattedArgs, chain) - .then((transaction) => { - resolve({ - transactionId: transaction.transactionHash, - transaction, - }); - toast({ - title: "Transaction is Sealed", - status: "success", - isClosable: true, - duration: 1000, - }); - }) - .catch((error) => { - reject(error); - toast({ - title: "Transaction failed", - status: "error", - isClosable: true, - duration: 1000, - }); - }); + !isUserOperation + ? method(address, formattedArgs, chain) + .then((transaction) => { + resolve({ + transactionId: transaction.transactionHash, + transaction, + }); + toast({ + title: "Transaction is Sealed", + status: "success", + isClosable: true, + duration: 1000, + }); + }) + .catch((error) => { + reject(error); + toast({ + title: "Transaction failed", + status: "error", + isClosable: true, + duration: 1000, + }); + }) + : method(address, formattedArgs, chain) + .then((userOpHash) => { + resolve({ userOpHash }); + toast({ + title: "Transaction is Sealed", + status: "success", + isClosable: true, + duration: 1000, + }); + }) + .catch((error) => { + reject(error); + toast({ + title: "Transaction failed", + status: "error", + isClosable: true, + duration: 1000, + }); + }); }); }, [toast, checkArgumentsAndAddress, chain] @@ -198,7 +225,11 @@ const EvmEditor = (): ReactJSXElement => { isSandboxDisabled shouldClearScript disabledTabs={[ScriptTypes.SCRIPT, ScriptTypes.RESOURCE]} - tabsShouldLoadDefaultTemplate={[ScriptTypes.SIGN, ScriptTypes.CONTRACT]} + tabsShouldLoadDefaultTemplate={[ + ScriptTypes.SIGN, + ScriptTypes.CONTRACT, + ScriptTypes.USER_OPERATION, + ]} faucetUrl={(chain as EvmChain) ? FaucetUrls[chain as EvmChain] : ""} > diff --git a/src/components/FlowEditor.tsx b/src/components/FlowEditor.tsx index bd504b8..81d40aa 100644 --- a/src/components/FlowEditor.tsx +++ b/src/components/FlowEditor.tsx @@ -210,7 +210,11 @@ const FlowEditor = (): ReactJSXElement => { onSendTransactions={handleSendTransactions} argTypes={typeKeys} isTransactionsExtraSignersAvailable - disabledTabs={[ScriptTypes.CONTRACT, ScriptTypes.RESOURCE]} + disabledTabs={[ + ScriptTypes.CONTRACT, + ScriptTypes.RESOURCE, + ScriptTypes.USER_OPERATION, + ]} tabsShouldLoadDefaultTemplate={[ScriptTypes.SIGN]} onSendScript={handleSendScript} faucetUrl="https://testnet-faucet.onflow.org/fund-account" diff --git a/src/components/SolanaEditor.tsx b/src/components/SolanaEditor.tsx index 24f0afc..e6d6723 100644 --- a/src/components/SolanaEditor.tsx +++ b/src/components/SolanaEditor.tsx @@ -142,6 +142,7 @@ const SolanaEditor = (): ReactJSXElement => { ScriptTypes.SCRIPT, ScriptTypes.SIGN, ScriptTypes.RESOURCE, + ScriptTypes.USER_OPERATION, ]} tabsShouldLoadDefaultTemplate={[ScriptTypes.CONTRACT]} faucetUrl="https://solfaucet.com/" diff --git a/src/contracts/arbitrum.ts b/src/contracts/arbitrum.ts index b99d40d..2c2938c 100644 --- a/src/contracts/arbitrum.ts +++ b/src/contracts/arbitrum.ts @@ -1,11 +1,20 @@ import { AbiItem } from "web3-utils"; -const contractAddress = "0xdc5fd9220511a7211719dd8206ec2d686054bcc0"; +const contractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739"; const contractAbi: AbiItem[] = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, { - inputs: [], - stateMutability: "nonpayable", - type: "constructor", + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "message", + type: "string", + }, + ], + name: "donateMessage", + type: "event", }, { anonymous: false, @@ -34,21 +43,16 @@ const contractAbi: AbiItem[] = [ type: "event", }, { - inputs: [ - { - internalType: "uint256", - name: "a", - type: "uint256", - }, - ], + inputs: [], + name: "_owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "a", type: "uint256" }], name: "arithmeticError", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "pure", type: "function", }, @@ -60,57 +64,54 @@ const contractAbi: AbiItem[] = [ type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "string", name: "message", type: "string" }], + name: "donate", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue", outputs: [], stateMutability: "nonpayable", type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue2", outputs: [], stateMutability: "nonpayable", type: "function", }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, { inputs: [], name: "value", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "value2", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, ]; export { contractAddress, contractAbi }; diff --git a/src/contracts/bsc.ts b/src/contracts/bsc.ts index b284777..2c2938c 100644 --- a/src/contracts/bsc.ts +++ b/src/contracts/bsc.ts @@ -1,11 +1,20 @@ import { AbiItem } from "web3-utils"; -const contractAddress = "0x3CC26344Aa3f2d12005f68CAc01EDaf0840e98F3"; +const contractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739"; const contractAbi: AbiItem[] = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, { - inputs: [], - stateMutability: "nonpayable", - type: "constructor", + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "message", + type: "string", + }, + ], + name: "donateMessage", + type: "event", }, { anonymous: false, @@ -34,21 +43,16 @@ const contractAbi: AbiItem[] = [ type: "event", }, { - inputs: [ - { - internalType: "uint256", - name: "a", - type: "uint256", - }, - ], + inputs: [], + name: "_owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "a", type: "uint256" }], name: "arithmeticError", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "pure", type: "function", }, @@ -60,57 +64,54 @@ const contractAbi: AbiItem[] = [ type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "string", name: "message", type: "string" }], + name: "donate", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue", outputs: [], stateMutability: "nonpayable", type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue2", outputs: [], stateMutability: "nonpayable", type: "function", }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, { inputs: [], name: "value", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "value2", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, ]; export { contractAddress, contractAbi }; diff --git a/src/contracts/fuji.ts b/src/contracts/fuji.ts index 7cb500a..115cdfd 100644 --- a/src/contracts/fuji.ts +++ b/src/contracts/fuji.ts @@ -1,11 +1,20 @@ import { AbiItem } from "web3-utils"; -const contractAddress = "0xDC5Fd9220511A7211719dD8206Ec2D686054bCC0"; +const contractAddress = "0xD76bAA840e3D5AE1C5E5C7cEeF1C1A238687860e"; const contractAbi: AbiItem[] = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, { - inputs: [], - stateMutability: "nonpayable", - type: "constructor", + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "message", + type: "string", + }, + ], + name: "donateMessage", + type: "event", }, { anonymous: false, @@ -34,21 +43,16 @@ const contractAbi: AbiItem[] = [ type: "event", }, { - inputs: [ - { - internalType: "uint256", - name: "a", - type: "uint256", - }, - ], + inputs: [], + name: "_owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "a", type: "uint256" }], name: "arithmeticError", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "pure", type: "function", }, @@ -60,57 +64,54 @@ const contractAbi: AbiItem[] = [ type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "string", name: "message", type: "string" }], + name: "donate", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue", outputs: [], stateMutability: "nonpayable", type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue2", outputs: [], stateMutability: "nonpayable", type: "function", }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, { inputs: [], name: "value", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "value2", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, ]; export { contractAddress, contractAbi }; diff --git a/src/contracts/goerli.ts b/src/contracts/goerli.ts new file mode 100644 index 0000000..2c2938c --- /dev/null +++ b/src/contracts/goerli.ts @@ -0,0 +1,117 @@ +import { AbiItem } from "web3-utils"; + +const contractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739"; +const contractAbi: AbiItem[] = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "message", + type: "string", + }, + ], + name: "donateMessage", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "updateValue", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "updateValue2", + type: "event", + }, + { + inputs: [], + name: "_owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "a", type: "uint256" }], + name: "arithmeticError", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "customError", + outputs: [], + stateMutability: "pure", + type: "function", + }, + { + inputs: [{ internalType: "string", name: "message", type: "string" }], + name: "donate", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], + name: "setValue", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], + name: "setValue2", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "value", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "value2", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; + +export { contractAddress, contractAbi }; diff --git a/src/contracts/index.ts b/src/contracts/index.ts index 7f805b2..aeacda0 100644 --- a/src/contracts/index.ts +++ b/src/contracts/index.ts @@ -12,9 +12,9 @@ import { contractAddress as mumbaiContractAddress, } from "./mumbai"; import { - contractAbi as rinkebyContractAbi, - contractAddress as rinkebyContractAddress, -} from "./rinkeby"; + contractAbi as goerliContractAbi, + contractAddress as goerliContractAddress, +} from "./goerli"; import { contractAbi as arbitrumContractAbi, contractAddress as arbitrumContractAddress, @@ -36,8 +36,8 @@ type ContractInfosType = { export const ContractInfos: ContractInfosType = { [EvmChain.Ethereum]: { - abi: rinkebyContractAbi, - address: rinkebyContractAddress, + abi: goerliContractAbi, + address: goerliContractAddress, }, [EvmChain.Bsc]: { abi: bscContractAbi, diff --git a/src/contracts/mumbai.ts b/src/contracts/mumbai.ts index cd3c669..2c2938c 100644 --- a/src/contracts/mumbai.ts +++ b/src/contracts/mumbai.ts @@ -1,11 +1,20 @@ import { AbiItem } from "web3-utils"; -const contractAddress = "0xDC5Fd9220511A7211719dD8206Ec2D686054bCC0"; +const contractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739"; const contractAbi: AbiItem[] = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, { - inputs: [], - stateMutability: "nonpayable", - type: "constructor", + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "message", + type: "string", + }, + ], + name: "donateMessage", + type: "event", }, { anonymous: false, @@ -34,21 +43,16 @@ const contractAbi: AbiItem[] = [ type: "event", }, { - inputs: [ - { - internalType: "uint256", - name: "a", - type: "uint256", - }, - ], + inputs: [], + name: "_owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "a", type: "uint256" }], name: "arithmeticError", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "pure", type: "function", }, @@ -60,56 +64,54 @@ const contractAbi: AbiItem[] = [ type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "string", name: "message", type: "string" }], + name: "donate", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue", outputs: [], stateMutability: "nonpayable", type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue2", outputs: [], stateMutability: "nonpayable", type: "function", }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, { inputs: [], name: "value", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "value2", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, ]; + export { contractAddress, contractAbi }; diff --git a/src/contracts/optimism.ts b/src/contracts/optimism.ts index 7cb500a..2c2938c 100644 --- a/src/contracts/optimism.ts +++ b/src/contracts/optimism.ts @@ -1,11 +1,20 @@ import { AbiItem } from "web3-utils"; -const contractAddress = "0xDC5Fd9220511A7211719dD8206Ec2D686054bCC0"; +const contractAddress = "0x009c403BdFaE357d82AAef2262a163287c30B739"; const contractAbi: AbiItem[] = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, { - inputs: [], - stateMutability: "nonpayable", - type: "constructor", + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "message", + type: "string", + }, + ], + name: "donateMessage", + type: "event", }, { anonymous: false, @@ -34,21 +43,16 @@ const contractAbi: AbiItem[] = [ type: "event", }, { - inputs: [ - { - internalType: "uint256", - name: "a", - type: "uint256", - }, - ], + inputs: [], + name: "_owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "a", type: "uint256" }], name: "arithmeticError", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "pure", type: "function", }, @@ -60,57 +64,54 @@ const contractAbi: AbiItem[] = [ type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "string", name: "message", type: "string" }], + name: "donate", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue", outputs: [], stateMutability: "nonpayable", type: "function", }, { - inputs: [ - { - internalType: "uint256", - name: "newValue", - type: "uint256", - }, - ], + inputs: [{ internalType: "uint256", name: "newValue", type: "uint256" }], name: "setValue2", outputs: [], stateMutability: "nonpayable", type: "function", }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, { inputs: [], name: "value", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "value2", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, + { + inputs: [], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, ]; export { contractAddress, contractAbi }; diff --git a/src/contracts/rinkeby.ts b/src/contracts/rinkeby.ts deleted file mode 100644 index 3fc588e..0000000 --- a/src/contracts/rinkeby.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { AbiItem } from "web3-utils"; - -const contractAddress = "0xe4500382e9e060925Eb9f60Ede902E9098F426d7"; -const contractAbi: AbiItem[] = [ - { - constant: true, - inputs: [], - name: "value", - outputs: [{ name: "", type: "uint256" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: false, - inputs: [{ name: "newValue", type: "uint256" }], - name: "setValue", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - constant: true, - inputs: [], - name: "value2", - outputs: [{ name: "", type: "uint256" }], - payable: false, - stateMutability: "view", - type: "function", - }, - { - constant: false, - inputs: [{ name: "newValue", type: "uint256" }], - name: "setValue2", - outputs: [], - payable: false, - stateMutability: "nonpayable", - type: "function", - }, - { - anonymous: false, - inputs: [{ indexed: false, name: "value", type: "uint256" }], - name: "updateValue", - type: "event", - }, - { - anonymous: false, - inputs: [{ indexed: false, name: "value", type: "uint256" }], - name: "updateValue2", - type: "event", - }, -]; - -export { contractAddress, contractAbi }; diff --git a/src/scripts/aptos/Modules.ts b/src/scripts/aptos/Modules.ts index cd3f7d6..5a261ec 100644 --- a/src/scripts/aptos/Modules.ts +++ b/src/scripts/aptos/Modules.ts @@ -61,7 +61,7 @@ export const transferAptosCoin = { comment: "coin type", value: "0x1::aptos_coin::AptosCoin", }, - { type: AptosArgTypes.Address, comment: "receipient", name: "receipient" }, + { type: AptosArgTypes.Address, comment: "recipient", name: "recipient" }, { type: AptosArgTypes.Number, comment: "value", name: "value" }, ], }; diff --git a/src/scripts/aptos/Script.ts b/src/scripts/aptos/Script.ts index 8d6b831..4f72527 100644 --- a/src/scripts/aptos/Script.ts +++ b/src/scripts/aptos/Script.ts @@ -94,7 +94,7 @@ export const transferTokenScript = { }, }, args: [ - { type: AptosArgTypes.Address, comment: "receipient", name: "receipient" }, + { type: AptosArgTypes.Address, comment: "recipient", name: "recipient" }, { type: AptosArgTypes.Number, comment: "value", name: "value" }, ], }; diff --git a/src/scripts/evm/Transactions.ts b/src/scripts/evm/Transactions.ts index 2ed829a..7614a6b 100644 --- a/src/scripts/evm/Transactions.ts +++ b/src/scripts/evm/Transactions.ts @@ -7,17 +7,17 @@ export const sendTokens = { script: "", method: ( account: string, - args: { receipient: string; amount: string }, + args: { recipient: string; amount: string }, chain: EvmChain ): Promise => ChainServices[chain].web3.eth.sendTransaction({ from: account, - to: args.receipient, + to: args.recipient, value: args.amount, }), args: [ { type: ArgTypes.String, comment: "amount(wei)", name: "amount" }, - { type: ArgTypes.String, comment: "receipient", name: "receipient" }, + { type: ArgTypes.String, comment: "recipient", name: "recipient" }, ], shouldSign: true, isArgsAdjustable: false, diff --git a/src/scripts/evm/UserOperations.ts b/src/scripts/evm/UserOperations.ts new file mode 100644 index 0000000..4a183ea --- /dev/null +++ b/src/scripts/evm/UserOperations.ts @@ -0,0 +1,152 @@ +import { ChainServices } from "../../services"; +import { EvmChain } from "../../types/ChainTypes"; +import ScriptTypes, { ArgTypes } from "../../types/ScriptTypes"; + +interface IUserOperation { + callData: string; + callGasLimit?: number; + verificationGasLimit?: number; + preVerificationGas?: number; + maxFeePerGas?: number; + maxPriorityFeePerGas?: number; + paymasterAndData?: string; +} + +interface Args { + type: ArgTypes; + comment: string; + name: string; + value?: string; +} +const userOperationRestArgs: Args[] = [ + { type: ArgTypes.Number, comment: "callGasLimit", name: "callGasLimit" }, + { + type: ArgTypes.Number, + comment: "verificationGasLimit", + name: "verificationGasLimit", + }, + { + type: ArgTypes.Number, + comment: "preVerificationGas", + name: "preVerificationGas", + }, + { + type: ArgTypes.Number, + comment: "maxFeePerGas", + name: "maxFeePerGas", + }, + { + type: ArgTypes.Number, + comment: "maxPriorityFeePerGas", + name: "maxPriorityFeePerGas", + }, + { + type: ArgTypes.String, + comment: "paymasterAndData", + name: "paymasterAndData", + }, +]; + +function getModifiedArgs(args: Args[], name: string, newValue: string): Args[] { + return args.map((item) => { + if (item.name === name) { + return { ...item, value: newValue }; + } else { + return item; + } + }); +} + +export const sendTokens = { + type: ScriptTypes.USER_OPERATION, + description: "Send native token", + method: ( + account: string, + args: IUserOperation, + chain: EvmChain + ): Promise => { + return ChainServices[chain].bloctoSDK.ethereum.sendUserOperation(args); + }, + args: [ + { + type: ArgTypes.String, + comment: "call data (hex)", + name: "callData", + value: + "b61d27f600000000000000000000000050504ab483c9bde3af9700b5fe77a860d81b3e4f00000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", + }, + ...userOperationRestArgs, + ], +}; + +export const transferErc20 = { + type: ScriptTypes.USER_OPERATION, + description: "Transfer erc20 token", + method: ( + account: string, + args: IUserOperation, + chain: EvmChain + ): Promise => { + return ChainServices[chain].bloctoSDK.ethereum.sendUserOperation(args); + }, + args: [ + { + type: ArgTypes.String, + comment: "call data (hex)", + name: "callData", + value: + "b61d27f60000000000000000000000002d7882bedcbfddce29ba99965dd3cdf7fcb10a1e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044a9059cbb00000000000000000000000050504ab483c9bde3af9700b5fe77a860d81b3e4f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000", + }, + ...userOperationRestArgs, + ], +}; + +export const setValue = { + type: ScriptTypes.USER_OPERATION, + description: "Call setValue function on contract", + method: ( + account: string, + args: IUserOperation, + chain: EvmChain + ): Promise => { + return ChainServices[chain].bloctoSDK.ethereum.sendUserOperation(args); + }, + args: [ + { + type: ArgTypes.String, + comment: "call data (hex)", + name: "callData", + value: + "b61d27f6000000000000000000000000dc5fd9220511a7211719dd8206ec2d686054bcc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002455241077000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000", + }, + ...userOperationRestArgs, + ], + shouldSign: true, +}; + +export const setValueWithCustomPaymaster = { + type: ScriptTypes.USER_OPERATION, + description: "Call setValue function on contract with custom paymaster", + method: ( + account: string, + args: IUserOperation, + chain: EvmChain + ): Promise => { + return ChainServices[chain].bloctoSDK.ethereum.sendUserOperation(args); + }, + args: [ + { + type: ArgTypes.String, + comment: "call data (hex)", + name: "callData", + value: + "b61d27f6000000000000000000000000dc5fd9220511a7211719dd8206ec2d686054bcc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002455241077000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000", + }, + ...getModifiedArgs( + userOperationRestArgs, + "paymasterAndData", + "411bafa5a252F47e27B399Ab48e0A7aDcB4256A10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006492d7d9dbaab7fcd442c32259de3c1a450c3a79d134fc813702dd9689d0415261e0c9004a39173aa923a93df22b1067414927405f4c92ab2692e858570605804ca89d4c1c" + ), + ], + shouldSign: true, +}; diff --git a/src/scripts/flow/Transactions.ts b/src/scripts/flow/Transactions.ts index 329094a..7a0ca88 100644 --- a/src/scripts/flow/Transactions.ts +++ b/src/scripts/flow/Transactions.ts @@ -84,7 +84,7 @@ transaction(amount: UFix64, to: Address) { }`, args: [ { type: "UFix64", comment: "amount" }, - { type: "Address", comment: "receipient" }, + { type: "Address", comment: "recipient" }, ], shouldSign: true, }; @@ -112,7 +112,7 @@ transaction(amount: UFix64, to: Address) { }`, args: [ { type: "UFix64", comment: "amount" }, - { type: "Address", comment: "receipient" }, + { type: "Address", comment: "recipient" }, ], shouldSign: true, }; @@ -154,7 +154,7 @@ transaction(amount: UFix64, to: Address) { }`, args: [ { type: "UFix64", comment: "amount" }, - { type: "Address", comment: "receipient" }, + { type: "Address", comment: "recipient" }, ], shouldSign: true, }; @@ -196,7 +196,7 @@ transaction(amount: UFix64, to: Address) { }`, args: [ { type: "UFix64", comment: "amount" }, - { type: "Address", comment: "receipient" }, + { type: "Address", comment: "recipient" }, ], shouldSign: true, }; diff --git a/src/scripts/solana/Transactions.ts b/src/scripts/solana/Transactions.ts index c5d7042..9cdff9b 100644 --- a/src/scripts/solana/Transactions.ts +++ b/src/scripts/solana/Transactions.ts @@ -14,7 +14,7 @@ export const sendSOL = { script: "", method: async ( account: string, - args: { receipient: string; amount: string } + args: { recipient: string; amount: string } ): Promise => { return new Promise(async (resolve, reject) => { try { @@ -28,7 +28,7 @@ export const sendSOL = { transaction.add( SystemProgram.transfer({ fromPubkey: publicKey, - toPubkey: new PublicKey(args.receipient), + toPubkey: new PublicKey(args.recipient), lamports: Number(args.amount), }) ); @@ -50,7 +50,7 @@ export const sendSOL = { }, args: [ { type: ArgTypes.String, comment: "amount(lamports)", name: "amount" }, - { type: ArgTypes.String, comment: "receipient", name: "receipient" }, + { type: ArgTypes.String, comment: "recipient", name: "recipient" }, ], isArgsAdjustable: false, }; diff --git a/src/services/arbitrum.ts b/src/services/arbitrum.ts index d7297be..d0ee865 100644 --- a/src/services/arbitrum.ts +++ b/src/services/arbitrum.ts @@ -1,6 +1,6 @@ import Web3 from "web3"; import BloctoSDK from "@blocto/sdk"; -import { ExtendedEvmBloctoSDK } from "./rinkeby"; +import { ExtendedEvmBloctoSDK } from "./goerli"; const isMainnet = process.env.REACT_APP_NETWORK === "mainnet"; diff --git a/src/services/bscTestnet.ts b/src/services/bscTestnet.ts index b5adfa8..68d8513 100644 --- a/src/services/bscTestnet.ts +++ b/src/services/bscTestnet.ts @@ -1,6 +1,6 @@ import Web3 from "web3"; import BloctoSDK from "@blocto/sdk"; -import { ExtendedEvmBloctoSDK } from "./rinkeby"; +import { ExtendedEvmBloctoSDK } from "./goerli"; const isMainnet = process.env.REACT_APP_NETWORK === "mainnet"; diff --git a/src/services/fuji.ts b/src/services/fuji.ts index 395e205..9e27c79 100644 --- a/src/services/fuji.ts +++ b/src/services/fuji.ts @@ -1,6 +1,6 @@ import Web3 from "web3"; import BloctoSDK from "@blocto/sdk"; -import { ExtendedEvmBloctoSDK } from "./rinkeby"; +import { ExtendedEvmBloctoSDK } from "./goerli"; const isMainnet = process.env.REACT_APP_NETWORK === "mainnet"; diff --git a/src/services/rinkeby.ts b/src/services/goerli.ts similarity index 90% rename from src/services/rinkeby.ts rename to src/services/goerli.ts index f3ff075..42b9a98 100644 --- a/src/services/rinkeby.ts +++ b/src/services/goerli.ts @@ -14,11 +14,11 @@ const isMainnet = process.env.REACT_APP_NETWORK === "mainnet"; const bloctoSDK = new BloctoSDK({ ethereum: { // (required) chainId to be used - chainId: isMainnet ? "0x1" : "0x4", + chainId: isMainnet ? "0x1" : "0x5", // (required for Ethereum) JSON RPC endpoint rpc: isMainnet ? "https://mainnet.infura.io/v3/ef5a5728e2354955b562d2ffa4ae5305" - : "https://rinkeby.blocto.app/", + : "https://rpc.ankr.com/eth_goerli", }, appId: process.env.REACT_APP_DAPP_ID, }) as ExtendedEvmBloctoSDK; diff --git a/src/services/index.ts b/src/services/index.ts index f0a760a..129f39f 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -10,10 +10,10 @@ import { web3 as arbitrumWeb3, bloctoSDK as arbitrumSDK } from "./arbitrum"; import { web3 as optimismWeb3, bloctoSDK as optimismSDK } from "./optimism"; import { web3 as mumbaiWeb3, bloctoSDK as mumbaiSDK } from "./mumbai"; import { - web3 as rinkebyWeb3, - bloctoSDK as rinkebySDK, + web3 as goerliWeb3, + bloctoSDK as goerliSDK, ExtendedEvmBloctoSDK, -} from "./rinkeby"; +} from "./goerli"; import { bloctoSDK as solanaSDK, ExtendedSolaneBloctoSDK, @@ -71,8 +71,8 @@ type ChainServicesType = FlowInfoType & export const ChainServices: ChainServicesType = { [Chains.Flow]: { address: null }, [Chains.Ethereum]: { - web3: rinkebyWeb3, - bloctoSDK: rinkebySDK, + web3: goerliWeb3, + bloctoSDK: goerliSDK, address: null, contract: null, }, diff --git a/src/services/mumbai.ts b/src/services/mumbai.ts index 14dee92..87142c2 100644 --- a/src/services/mumbai.ts +++ b/src/services/mumbai.ts @@ -1,6 +1,6 @@ import Web3 from "web3"; import BloctoSDK from "@blocto/sdk"; -import { ExtendedEvmBloctoSDK } from "./rinkeby"; +import { ExtendedEvmBloctoSDK } from "./goerli"; const isMainnet = process.env.REACT_APP_NETWORK === "mainnet"; diff --git a/src/services/optimism.ts b/src/services/optimism.ts index b250f03..efb05f3 100644 --- a/src/services/optimism.ts +++ b/src/services/optimism.ts @@ -1,6 +1,6 @@ import Web3 from "web3"; import BloctoSDK from "@blocto/sdk"; -import { ExtendedEvmBloctoSDK } from "./rinkeby"; +import { ExtendedEvmBloctoSDK } from "./goerli"; const isMainnet = process.env.REACT_APP_NETWORK === "mainnet"; diff --git a/src/types/ScriptTypes.ts b/src/types/ScriptTypes.ts index 400b648..9f0405b 100644 --- a/src/types/ScriptTypes.ts +++ b/src/types/ScriptTypes.ts @@ -4,6 +4,7 @@ enum ScriptTypes { CONTRACT, SIGN, RESOURCE, + USER_OPERATION, } export default ScriptTypes; diff --git a/yarn.lock b/yarn.lock index f466e8b..5ba48d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1301,12 +1301,12 @@ "@onflow/util-template" "^1.0.1" "@onflow/util-uid" "^1.0.1" -"@blocto/sdk@0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@blocto/sdk/-/sdk-0.4.3.tgz#d151a1b98dd95be9e27fa7b0026fad1d308eb854" - integrity sha512-Dtk19jknv7J4xKOfGwdsp7gdgcCqc2Fg4KIkHHFb8N9iMqFmzFoIizDmX5HzuyBxVhExM8Q61Y0Ndxzutz55mQ== +"@blocto/sdk@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@blocto/sdk/-/sdk-0.5.0.tgz#05c32f977a81dcd1f89a98692a4a85bf17176132" + integrity sha512-brAVBey2bGf6fA8U7A9SHTU0mjbe4BrVeBgOfCmjPr5DQWaIG9G8fqsam3Fdviv6U9bKOpt1b8za2fOkQYYHzA== dependencies: - bs58 "^4.0.1" + bs58 "^5.0.0" buffer "^6.0.3" eip1193-provider "^1.0.1" js-sha3 "^0.8.0" @@ -4238,6 +4238,11 @@ base-x@^3.0.2, base-x@^3.0.8: dependencies: safe-buffer "^5.0.1" +base-x@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" + integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== + base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -4521,6 +4526,13 @@ bs58@^4.0.0, bs58@^4.0.1: dependencies: base-x "^3.0.2" +bs58@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" + integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== + dependencies: + base-x "^4.0.0" + bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" @@ -6991,16 +7003,11 @@ focus-lock@^0.9.1: dependencies: tslib "^2.0.3" -follow-redirects@^1.0.0: +follow-redirects@^1.0.0, follow-redirects@^1.14.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity "sha1-tGCGQUS6Y/JoEJbydMTlcCbaLBM= sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" -follow-redirects@^1.14.0: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -14551,7 +14558,12 @@ ws@^6.2.1: dependencies: async-limiter "~1.0.0" -ws@^7.4.0, ws@^7.4.5: +ws@^7.4.0: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + +ws@^7.4.5: version "7.5.7" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==