diff --git a/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/gnosis_safe.json b/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/gnosis_safe.json new file mode 100644 index 000000000..2a26ee841 --- /dev/null +++ b/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/gnosis_safe.json @@ -0,0 +1,1199 @@ +{ + "defaultAddress": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "released": true, + "contractName": "GnosisSafe", + "version": "1.3.0", + "networkAddresses": { + "1": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "3": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "4": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "5": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "10": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "11": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "12": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "18": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "25": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "28": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "30": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "31": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "39": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "40": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "41": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "42": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "44": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "46": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "50": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "51": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "56": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "57": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "61": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "63": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "69": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "81": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "82": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "83": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "97": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "100": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "106": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "108": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "111": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "122": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "123": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "137": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "148": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "155": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "246": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "250": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "280": "0xB00ce5CCcdEf57e539ddcEd01DF43a13855d9910", + "288": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "291": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "300": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "321": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "322": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "324": "0xB00ce5CCcdEf57e539ddcEd01DF43a13855d9910", + "336": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "338": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "420": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "424": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "570": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "588": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "592": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "595": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "599": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "686": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "787": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1001": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1008": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1088": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1101": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1111": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1112": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1115": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1116": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1230": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1231": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1284": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1285": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1287": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1294": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1442": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1559": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1807": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1890": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1891": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1984": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "2001": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "2002": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "2008": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "2019": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "2020": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "2021": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "2221": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "2222": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "3737": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "4002": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "4460": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "4689": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "4918": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "4919": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "5000": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "5001": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "5700": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "58008": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "6102": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "7001": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "7341": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "7700": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "8217": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "8453": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "9000": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "9001": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "9728": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "10000": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "10001": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "10081": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "10200": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "10243": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "11235": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "11437": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "11891": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "12357": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "17000": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "23294": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "23295": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "42161": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "42170": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "42220": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "43113": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "43114": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "43288": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "44787": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "45000": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "47805": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "54211": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "56288": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "57000": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "59140": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "59144": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "71401": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "71402": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "73799": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "80001": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "84531": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "200101": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "200202": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "333999": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "421611": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "421613": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "421614": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "534351": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "534352": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "534353": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "622277": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "11155111": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "7777777": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "245022926": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "245022934": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "222000222": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "333000333": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1313161554": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1313161555": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "1666600000": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "1666700000": "0x69f4D1788e39c87893C980c06EdF4b7f686e2938", + "11297108099": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "11297108109": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552" + }, + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "AddedOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "approvedHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ApproveHash", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "handler", + "type": "address" + } + ], + "name": "ChangedFallbackHandler", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "guard", + "type": "address" + } + ], + "name": "ChangedGuard", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "ChangedThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "DisabledModule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "EnabledModule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "payment", + "type": "uint256" + } + ], + "name": "ExecutionFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ExecutionFromModuleFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ExecutionFromModuleSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "payment", + "type": "uint256" + } + ], + "name": "ExecutionSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "RemovedOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "initiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "initializer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "fallbackHandler", + "type": "address" + } + ], + "name": "SafeSetup", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "SignMsg", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "addOwnerWithThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hashToApprove", + "type": "bytes32" + } + ], + "name": "approveHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "approvedHashes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "changeThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dataHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "requiredSignatures", + "type": "uint256" + } + ], + "name": "checkNSignatures", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dataHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + } + ], + "name": "checkSignatures", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prevModule", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "disableModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "domainSeparator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "enableModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "safeTxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "gasToken", + "type": "address" + }, + { + "internalType": "address", + "name": "refundReceiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + } + ], + "name": "encodeTransactionData", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "safeTxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "gasToken", + "type": "address" + }, + { + "internalType": "address payable", + "name": "refundReceiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + } + ], + "name": "execTransaction", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + } + ], + "name": "execTransactionFromModule", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + } + ], + "name": "execTransactionFromModuleReturnData", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "start", + "type": "address" + }, + { + "internalType": "uint256", + "name": "pageSize", + "type": "uint256" + } + ], + "name": "getModulesPaginated", + "outputs": [ + { + "internalType": "address[]", + "name": "array", + "type": "address[]" + }, + { + "internalType": "address", + "name": "next", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOwners", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "getStorageAt", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "safeTxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "gasToken", + "type": "address" + }, + { + "internalType": "address", + "name": "refundReceiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + } + ], + "name": "getTransactionHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "isModuleEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "isOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prevOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "removeOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + } + ], + "name": "requiredTxGas", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "handler", + "type": "address" + } + ], + "name": "setFallbackHandler", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guard", + "type": "address" + } + ], + "name": "setGuard", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_owners", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "address", + "name": "fallbackHandler", + "type": "address" + }, + { + "internalType": "address", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "paymentReceiver", + "type": "address" + } + ], + "name": "setup", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "signedMessages", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetContract", + "type": "address" + }, + { + "internalType": "bytes", + "name": "calldataPayload", + "type": "bytes" + } + ], + "name": "simulateAndRevert", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prevOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "oldOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "swapOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ] +} diff --git a/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/multi_send.json b/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/multi_send.json new file mode 100644 index 000000000..289139ac1 --- /dev/null +++ b/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/multi_send.json @@ -0,0 +1,186 @@ +{ + "defaultAddress": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "released": true, + "contractName": "MultiSend", + "version": "1.3.0", + "networkAddresses": { + "1": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "3": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "4": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "5": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "10": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "11": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "12": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "18": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "25": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "28": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "30": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "31": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "39": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "40": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "41": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "42": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "44": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "46": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "50": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "51": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "56": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "57": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "61": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "63": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "69": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "81": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "82": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "83": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "97": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "100": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "106": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "108": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "111": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "122": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "123": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "137": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "148": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "155": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "246": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "250": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "280": "0x0dFcccB95225ffB03c6FBB2559B530C2B7C8A912", + "288": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "291": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "300": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "321": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "322": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "324": "0x0dFcccB95225ffB03c6FBB2559B530C2B7C8A912", + "336": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "338": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "420": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "424": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "570": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "588": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "592": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "595": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "599": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "686": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "787": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1001": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1008": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1088": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1101": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1111": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1112": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1115": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1116": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1230": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1231": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1284": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1285": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1287": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1294": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1442": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1559": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1807": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1890": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1891": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1984": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "2001": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "2002": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "2008": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "2019": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "2020": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "2021": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "2221": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "2222": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "3737": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "4002": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "4460": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "4689": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "4918": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "4919": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "5000": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "5001": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "5700": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "6102": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "7001": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "7341": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "7700": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "8217": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "8453": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "9000": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "9001": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "9728": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "10000": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "10001": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "10081": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "10200": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "10243": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "11235": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "11437": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "11891": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "12357": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "17000": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "23294": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "23295": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "42161": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "42170": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "42220": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "43113": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "43114": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "43288": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "44787": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "45000": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "47805": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "54211": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "56288": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "57000": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "58008": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "59140": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "59144": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "71401": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "71402": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "73799": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "80001": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "84531": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "200101": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "200202": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "333999": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "421611": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "421613": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "421614": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "534351": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "534352": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "534353": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "622277": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "7777777": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "11155111": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "245022926": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "245022934": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "222000222": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "333000333": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1313161554": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1313161555": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "1666600000": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "1666700000": "0x998739BFdAAdde7C933B942a68053933098f9EDa", + "11297108099": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761", + "11297108109": "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761" + }, + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "transactions", + "type": "bytes" + } + ], + "name": "multiSend", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ] +} diff --git a/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/multi_send_call_only.json b/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/multi_send_call_only.json new file mode 100644 index 000000000..305437385 --- /dev/null +++ b/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/multi_send_call_only.json @@ -0,0 +1,181 @@ +{ + "defaultAddress": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "released": true, + "contractName": "MultiSendCallOnly", + "version": "1.3.0", + "networkAddresses": { + "1": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "3": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "4": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "5": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "10": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "11": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "12": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "18": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "25": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "28": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "30": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "31": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "39": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "40": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "41": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "42": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "44": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "46": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "50": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "51": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "56": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "57": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "61": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "63": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "69": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "81": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "82": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "83": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "97": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "100": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "106": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "108": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "111": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "122": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "123": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "137": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "148": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "155": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "246": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "250": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "280": "0xf220D3b4DFb23C4ade8C88E526C1353AbAcbC38F", + "288": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "291": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "300": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "321": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "322": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "324": "0xf220D3b4DFb23C4ade8C88E526C1353AbAcbC38F", + "336": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "338": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "420": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "424": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "570": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "588": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "592": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "595": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "599": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "686": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "787": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1001": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1008": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1088": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1101": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1111": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1112": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1115": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1116": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1230": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1231": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1284": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1285": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1287": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1294": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1442": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1559": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1807": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1890": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1891": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1984": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "2001": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "2002": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "2008": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "2019": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "2020": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "2021": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "2221": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "2222": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "3737": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "4002": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "4460": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "4689": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "4918": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "4919": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "5000": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "5001": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "5700": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "6102": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "7001": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "7341": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "7700": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "8217": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "8453": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "9000": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "9001": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "9728": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "10000": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "10001": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "10081": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "10200": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "10243": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "11235": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "11437": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "11891": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "12357": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "17000": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "23294": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "23295": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "42161": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "42170": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "42220": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "43113": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "43114": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "43288": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "44787": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "45000": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "47805": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "54211": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "56288": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "57000": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "58008": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "59140": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "59144": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "71401": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "71402": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "73799": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "80001": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "84531": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "200101": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "200202": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "333999": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "421611": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "421613": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "421614": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "534351": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "534352": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "534353": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "622277": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "11155111": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "7777777": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "245022926": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "245022934": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "222000222": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "333000333": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1313161554": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1313161555": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "1666600000": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "1666700000": "0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B", + "11297108099": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "11297108109": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D" + }, + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "transactions", + "type": "bytes" + } + ], + "name": "multiSend", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ] +} diff --git a/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/simulate_tx_accessor.json b/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/simulate_tx_accessor.json new file mode 100644 index 000000000..8591ad2ae --- /dev/null +++ b/apps/dapp/abi/@safe-global/safe-deployments/v1.3.0/simulate_tx_accessor.json @@ -0,0 +1,215 @@ +{ + "defaultAddress": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "released": true, + "contractName": "SimulateTxAccessor", + "version": "1.3.0", + "networkAddresses": { + "1": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "3": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "4": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "5": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "10": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "11": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "12": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "18": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "25": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "28": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "30": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "31": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "39": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "40": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "41": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "42": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "44": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "46": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "50": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "51": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "56": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "57": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "61": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "63": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "69": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "81": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "82": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "83": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "97": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "100": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "106": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "108": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "111": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "122": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "123": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "137": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "148": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "155": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "246": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "250": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "280": "0x4191E2e12E8BC5002424CE0c51f9947b02675a44", + "288": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "291": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "300": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "321": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "322": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "324": "0x4191E2e12E8BC5002424CE0c51f9947b02675a44", + "336": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "338": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "420": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "570": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "588": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "592": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "595": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "599": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "686": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "787": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1001": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1008": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1088": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1101": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1111": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1112": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1115": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1116": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1230": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1231": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1284": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1285": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1287": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1294": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1442": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1559": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1807": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1890": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1891": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1984": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "2001": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "2002": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "2008": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "2019": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "2020": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "2021": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "2221": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "2222": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "3737": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "4002": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "4460": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "4689": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "4918": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "4919": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "5000": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "5001": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "5700": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "6102": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "7001": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "7341": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "7700": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "8217": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "8453": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "9000": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "9001": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "9728": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "10000": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "10001": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "10081": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "10200": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "10243": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "11235": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "11437": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "11891": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "12357": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "17000": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "23294": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "23295": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "42161": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "42170": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "42220": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "43113": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "43114": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "43288": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "44787": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "45000": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "47805": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "54211": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "56288": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "57000": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "59140": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "59144": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "71401": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "71402": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "73799": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "80001": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "84531": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "200101": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "200202": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "333999": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "421611": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "421613": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "421614": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "534351": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "534352": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "534353": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "622277": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "7777777": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "11155111": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "245022926": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "245022934": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "222000222": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "333000333": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1313161554": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1313161555": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "1666600000": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "1666700000": "0x727a77a074D1E6c4530e814F89E618a3298FC044", + "11297108099": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da", + "11297108109": "0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da" + }, + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + } + ], + "name": "simulate", + "outputs": [ + { + "internalType": "uint256", + "name": "estimate", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} diff --git a/apps/dapp/package.json b/apps/dapp/package.json index 1a5d27092..c73814f6f 100644 --- a/apps/dapp/package.json +++ b/apps/dapp/package.json @@ -2,11 +2,11 @@ "name": "@temple/dapp", "version": "0.1.1", "engines": { - "node": ">=20.0.0" + "node": "20.x" }, "scripts": { - "prepare": "yarn typechain", "typechain": "typechain --target=ethers-v5 --out-dir src/types/typechain --glob abi/**/*.json", + "prepare": "yarn typechain && yarn codegen:safe-api-v1", "dev": "vite", "compile": "tsc", "vite:build": "vite build", @@ -14,12 +14,15 @@ "serve": "vite preview", "version:release": "standard-version", "version:prerelease": "standard-version --prerelease beta", - "build-with-stats": "tsc && BUILD_STATS=true vite build" + "build-with-stats": "tsc && BUILD_STATS=true vite build", + "safe-api-v1-host": "(cd src/safe/open-api && ./replace-host.sh && rm -f apiv1.jsone)", + "codegen:safe-api-v1": "yarn safe-api-v1-host && openapi --input ./src/safe/open-api/apiV1.json --output ./src/safe/open-api/client" }, "dependencies": { "@balancer-labs/sdk": "^1.0.4", "@safe-global/safe-apps-provider": "^0.18.0", "@safe-global/safe-apps-sdk": "^8.1.0", + "@safe-global/safe-core-sdk-types": "2.3.0", "@tanstack/react-query": "^4.36.1", "@tippyjs/react": "^4.2.6", "@web3-onboard/coinbase": "^2.2.5", @@ -32,6 +35,7 @@ "buffer": "^6.0.3", "d3-shape": "^3.0.1", "date-fns": "^2.28.0", + "ethereumjs-util": "^7.1.5", "ethers": "5.7.0", "events": "^3.3.0", "howler": "^2.2.3", @@ -53,12 +57,14 @@ "tippy.js": "^6.3.7", "use-debounce": "^9.0.2", "use-interval": "^1.4.0", - "util": "^0.12.4" + "util": "^0.12.4", + "zksync-web3": "^0.17.1" }, "devDependencies": { "@babel/core": "^7.16.0", "@commitlint/cli": "^15.0.0", "@commitlint/config-conventional": "^15.0.0", + "@gnosis.pm/safe-contracts": "^1.3.0", "@nomiclabs/hardhat-ethers": "2.2.1", "@synthetixio/synpress": "^1.2.0", "@typechain/ethers-v5": "10.1.0", @@ -72,6 +78,7 @@ "@types/react-dom": "^17.0.0", "@types/react-select": "^4.0.18", "@types/react-vis": "^1.11.10", + "@types/semver": "^7.5.6", "@types/styled-components": "^5.1.15", "@typescript-eslint/eslint-plugin": "^5.4.0", "@typescript-eslint/parser": "^5.4.0", @@ -87,6 +94,7 @@ "eslint-plugin-react": "^7.27.1", "eslint-plugin-react-hooks": "^4.3.0", "lint-staged": ">=10", + "openapi-typescript-codegen": "^0.25.0", "prettier": "^2.5.0", "standard-version": "^9.3.2", "tsconfig-paths-webpack-plugin": "^3.5.2", diff --git a/apps/dapp/src/assets/icons/copy.svg b/apps/dapp/src/assets/icons/copy.svg new file mode 100644 index 000000000..4e5416578 --- /dev/null +++ b/apps/dapp/src/assets/icons/copy.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/apps/dapp/src/assets/icons/link.svg b/apps/dapp/src/assets/icons/link.svg index 886f4fed2..b2178eafe 100644 --- a/apps/dapp/src/assets/icons/link.svg +++ b/apps/dapp/src/assets/icons/link.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/apps/dapp/src/components/Button/Button.tsx b/apps/dapp/src/components/Button/Button.tsx index 07b10f8df..db7750694 100644 --- a/apps/dapp/src/components/Button/Button.tsx +++ b/apps/dapp/src/components/Button/Button.tsx @@ -1,4 +1,4 @@ -import { HTMLProps, useState } from 'react'; +import { HTMLProps, MouseEvent, useState } from 'react'; import Image from 'components/Image/Image'; import styled, { css } from 'styled-components'; @@ -12,7 +12,7 @@ export interface ButtonProps label?: string; loading?: boolean; - onClick?(): Promise | void; + onClick?(e?: MouseEvent): Promise | void; } /** @@ -37,7 +37,7 @@ export const Button = ({ * Click handler which shows a spinner while the action is in progress. * If button is already in progress then callback is not called. */ - const onClickHandler = async () => { + const onClickHandler = async (e: MouseEvent) => { if (isLoading) { return; } @@ -47,7 +47,7 @@ export const Button = ({ setIsLoading(true); try { - await onClick(); + await onClick(e); } catch (err) { /* TODO: Handle JSON-RPC errors better */ // @ts-ignore diff --git a/apps/dapp/src/components/Charts/BiAxialAreaChart.tsx b/apps/dapp/src/components/Charts/BiAxialAreaChart.tsx index 11711589a..db0b9b256 100644 --- a/apps/dapp/src/components/Charts/BiAxialAreaChart.tsx +++ b/apps/dapp/src/components/Charts/BiAxialAreaChart.tsx @@ -2,7 +2,16 @@ import type { DataKey } from 'recharts/types/util/types'; import React from 'react'; import { useTheme } from 'styled-components'; -import { ResponsiveContainer, AreaChart as RechartsChart, Area, XAxis, YAxis, Tooltip, Legend, CartesianGrid } from 'recharts'; +import { + ResponsiveContainer, + AreaChart as RechartsChart, + Area, + XAxis, + YAxis, + Tooltip, + Legend, + CartesianGrid, +} from 'recharts'; import { formatNumberAbbreviated, formatNumberFixedDecimals } from 'utils/formatter'; import { useMediaQuery } from 'react-responsive'; import { queryPhone } from 'styles/breakpoints'; @@ -37,7 +46,7 @@ export default function BiAxialLineChart(props: React.PropsWithChildren - + {lines.map((line) => ( (props: React.PropsWithChildren - {lines.length > 1 ? : null} + {lines.length > 1 ? ( + + ) : null} ); diff --git a/apps/dapp/src/components/Copy/Copy.tsx b/apps/dapp/src/components/Copy/Copy.tsx new file mode 100644 index 000000000..c1e563c18 --- /dev/null +++ b/apps/dapp/src/components/Copy/Copy.tsx @@ -0,0 +1,15 @@ +import Tooltip from "components/Tooltip/Tooltip"; +import CopyIcon from 'assets/icons/copy.svg?react'; +import { theme } from 'styles/theme'; + +interface CopyProps { + value: string; +} +export const Copy = ({value}: CopyProps) => { + + return ( + Copy} position={'top'}> + navigator.clipboard.writeText(value)} /> + + ); +}; diff --git a/apps/dapp/src/components/InputSelect/InputSelect.tsx b/apps/dapp/src/components/InputSelect/InputSelect.tsx index 7d575ecdc..b427f7c76 100644 --- a/apps/dapp/src/components/InputSelect/InputSelect.tsx +++ b/apps/dapp/src/components/InputSelect/InputSelect.tsx @@ -62,13 +62,14 @@ export const InputSelect = (props: SelectTempleDaoProps) => { cursor: 'pointer', height: selectHeight, zIndex: props.zIndex ? Number(props.zIndex) + 1 : 2, // place it above the menu 👇 - width: props.width, + width: props.width ?? '100%', }), menu: (base, state) => ({ ...base, paddingTop: '1.5rem', marginTop: '-1.5rem', border: `0.0625rem solid ${theme.palette.brand}`, + width: props.width ?? '100%', zIndex: props.zIndex ?? 1, }), menuList: (base, state) => ({ diff --git a/apps/dapp/src/components/Pages/Core/DappPages/Borrow/index.tsx b/apps/dapp/src/components/Pages/Core/DappPages/Borrow/index.tsx index c89a3e0a2..f1adf3b23 100644 --- a/apps/dapp/src/components/Pages/Core/DappPages/Borrow/index.tsx +++ b/apps/dapp/src/components/Pages/Core/DappPages/Borrow/index.tsx @@ -299,7 +299,7 @@ export const BorrowPage = () => { const tlcContract = new TempleLineOfCredit__factory(signer).attach(env.contracts.tlc); const amount = getBigNumberFromString(state.borrowValue, getTokenInfo(state.outputToken).decimals); try { - const tx = await tlcContract.borrow(amount, wallet, { gasLimit: 350000 }); + const tx = await tlcContract.borrow(amount, wallet, { gasLimit: 500000 }); const receipt = await tx.wait(); openNotification({ title: `Borrowed ${state.borrowValue} DAI`, diff --git a/apps/dapp/src/components/Pages/Safe/admin/SafeTxDataTable.tsx b/apps/dapp/src/components/Pages/Safe/admin/SafeTxDataTable.tsx new file mode 100644 index 000000000..8bb0611e9 --- /dev/null +++ b/apps/dapp/src/components/Pages/Safe/admin/SafeTxDataTable.tsx @@ -0,0 +1,275 @@ +import { useState, useEffect, useRef, Fragment, MouseEvent } from 'react'; +import { LoadingText } from 'components/Pages/Core/components/LoaderVault/commons/LoadingText'; +import env from 'constants/env'; +import styled from 'styled-components'; +import { loading } from 'utils/loading-value'; +import { Button } from 'components/Button/Button'; +import { SafeStatus, SafeTransactionCategory, useSafeTransactions } from 'safe/safeContext'; +import dropdownIcon from 'assets/icons/dropdown.svg?react'; +import { Copy } from 'components/Copy/Copy'; + +export type SafeTableRow = { + date: string; + txHash?: string; + safeTxHash: string; + status: SafeStatus; + confirmations: string; + alreadySigned: boolean; + type: string; + isOwner: boolean; + nonce: number; + isExpanded: boolean; + dataRaw: string | null | undefined; + dataDecode: string; + button: { + label: string; + disabled: boolean; + }; + action: () => void; +}; + +type Props = { + safeTxCategory: SafeTransactionCategory; + tableHeaders: string[]; +}; + +export const SafeTxsDataTable = (props: Props) => { + const { safeTxCategory, tableHeaders } = props; + const [safeTableRows, setSafeTableRows] = useState>([]); + const safeTransactions = useSafeTransactions(); + const ref = useRef(null); + + useEffect(() => { + async function loadDataSubset() { + const dataSubset = await safeTransactions.tableRows(safeTxCategory, updateSafeTableRow); + if (!dataSubset) return; + setSafeTableRows(dataSubset); + } + loadDataSubset(); + }, [safeTransactions, safeTxCategory]); + + const updateSafeTableRow = (safeTxHash: string, newValue?: SafeTableRow) => { + setSafeTableRows((prevState) => { + const newState = prevState.map((prevStateSafeRow) => { + if (safeTxHash === prevStateSafeRow.safeTxHash) { + return { ...prevStateSafeRow, ...newValue }; + } else { + return { ...prevStateSafeRow }; + } + }); + return newState; + }); + }; + + return ( + + + + {tableHeaders.map((h, i) => ( + + + {h} + + + ))} + + + + {safeTransactions.isLoading() ? ( + loadSkeletonRows(1, tableHeaders.length) + ) : !safeTableRows || safeTableRows.length === 0 ? ( + + No data available + + ) : ( + <> + {safeTableRows.map((row) => { + return ( + + { + updateSafeTableRow(row.safeTxHash, { ...row, isExpanded: !row.isExpanded }); + }} + > + + + {row.nonce} + {row.status} + {row.type} + {row.confirmations} + + + {row.date} + {row.isExpanded ? : } + + + + {row.isExpanded && ( + + + {row.txHash && ( + + )} + + {row.dataRaw && ( + <> + + + + )} + + + )} + + ); + })} + + )} + + + ); +}; + +const loadSkeletonRows = (skeletonRowsNo: number, skeletonColumnsNo: number) => { + return [...Array(skeletonRowsNo)].map((_, index) => ( + + {[...Array(skeletonColumnsNo)].map( + ( + _, + i // Adds x no of loading cells, same as no of table headers + ) => ( + + + + ) + )} + + )); +}; + +type ExpandedDataRowProps = { + label: string; + value: string; + sliceValue?: boolean; + externalLink?: string; +}; + +const ExpandedDataRow = ({ label, value, externalLink, sliceValue = true }: ExpandedDataRowProps) => { + const ExpandedContainer = styled.div` + display: flex; + flex-direction: row; + padding: 0 10px 2px 10px; + align-items: baseline; + gap: 10px; + `; + const Label = styled.label` + font-weight: bold; + color: ${({ theme }) => theme.palette.brand}; + `; + const Pre = styled.pre` + font-size: smaller; + margin: 0; + `; + return ( + + + + {externalLink ? ( + + {value} + + ) : ( +
{value.length > 70 && sliceValue ? value?.slice(0, 65) + '...' : value}
+ )} + + ); +}; + +const TableHeader = styled.th` + vertical-align: top; + text-align: left; + padding-top: 0.5rem; +`; + +const HeaderTitleContainer = styled.div` + margin-right: 5px; +`; + +const HeaderRow = styled.tr` + white-space: nowrap; +`; + +const InnerDataRow = styled.div` + display: flex; + height: 1.5rem; + font-size: 12px; +`; + +const DataTable = styled.table` + border-collapse: collapse; + width: 100%; + color: ${({ theme }) => theme.palette.brand}; +`; + +const DataRow = styled.tr<{ hasBorderBotton: boolean; cursorPointer?: boolean }>` + overflow: hidden; + white-space: nowrap; + border-top: 1px solid ${({ theme }) => theme.palette.brand}; + cursor: ${({ cursorPointer }) => (cursorPointer ? 'pointer' : 'unset')}; + ${({ hasBorderBotton, theme }) => + `border-bottom: 1px solid ${hasBorderBotton ? theme.palette.brand : theme.palette.dark};`} +`; + +const DataCell = styled.td<{ isHidden?: boolean }>` + position: relative; + padding: 10px 10px 10px 0; + ${({ isHidden }) => isHidden && 'display: none;'} + font-size: 13px; + font-weight: 700; + text-align: left; + color: ${({ theme }) => theme.palette.brandLight}; +`; + +const LinkStyled = styled.a` + color: ${({ theme }) => theme.palette.brandLight}; + font-size: 0.9rem; + font-weight: 700; + &:hover { + color: ${({ theme }) => theme.palette.brandDark}; + } +`; + +const FlexContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; +`; + +const ArrowDown = styled(dropdownIcon)` + fill: ${({ theme }) => theme.palette.brand}; +`; + +const ArrowUp = styled(dropdownIcon)` + fill: ${({ theme }) => theme.palette.brand}; + transform: rotate(180deg); +`; diff --git a/apps/dapp/src/components/Pages/Safe/admin/index.tsx b/apps/dapp/src/components/Pages/Safe/admin/index.tsx new file mode 100644 index 000000000..d1b128289 --- /dev/null +++ b/apps/dapp/src/components/Pages/Safe/admin/index.tsx @@ -0,0 +1,143 @@ +import styled from 'styled-components'; +import { useState } from 'react'; +import env from 'constants/env'; +import { InputSelect, Option } from 'components/InputSelect/InputSelect'; +import { SafeTxsDataTable } from './SafeTxDataTable'; +import { queryPhone } from 'styles/breakpoints'; +import { useMediaQuery } from 'react-responsive'; +import { SafeTransactionCategory, SafeTransactionsContextProvider, useSafeTransactions } from 'safe/safeContext'; +import LinkIcon from 'assets/icons/link.svg?react'; +import { Copy } from 'components/Copy/Copy'; + +const SafeAdminWithContext = () => { + const [safeWalletAddress, setSafeWalletAddress] = useState(env.safes[0].address); + return ( + + + + ); +}; + +type SafeAdminProps = { + setSafeWalletAddress: (safeWallet: string) => void; +}; + +const SafeAdmin = ({ setSafeWalletAddress }: SafeAdminProps) => { + const isAbovePhone = useMediaQuery({ + query: queryPhone, + }); + const { safeAddress } = useSafeTransactions(); + + const safeWalletOptions: Option[] = env.safes.map((safe) => ({ + label: `${safe.name} (${safe.address.slice(0, 5)}...${safe.address.slice( + safe.address.length - 5, + safe.address.length + )})`, + value: safe.address, + })); + + return ( + + +
+

Safe App

+
+ + setSafeWalletAddress(e.value)} + isSearchable={false} + width={isAbovePhone ? '450px' : '300px'} + /> + + +
+
+
+ +
+
+ +
+
+
+ ); +}; + +export default SafeAdminWithContext; + +const Container = styled.div` + gap: 2rem; +`; + +const AreaDelimiter = styled.div` + h3 { + margin-top: 0.5rem; + margin-bottom: 0; + } + display: flex; + border: ${({ theme }) => `1px solid ${theme.palette.brand}`}; + border-radius: 2rem; + padding: 1rem; + flex-direction: column; +`; + +type SectionProps = { + label: string; + children: React.ReactNode; + safeTxCategoryLink?: SafeTransactionCategory; + overflowX?: boolean; +}; +const Section = (props: SectionProps) => { + const ENV_VARS = import.meta.env; + const ENV = ENV_VARS.VITE_ENV; + const IS_PROD = ENV === 'production'; + const safeEnv = IS_PROD ? 'eth' : 'sep'; + + const { label, children, safeTxCategoryLink } = props; + const { safeAddress } = useSafeTransactions(); + + return ( + + + + {safeTxCategoryLink && ( + + + + )} + + {children} + + ); +}; + +const SectionContainer = styled.div<{ overflowX?: boolean }>` + display: flex; + flex-direction: column; + margin-top: 3rem; + overflow-x: ${({ overflowX }) => (overflowX ? 'auto' : 'unset')}; +`; + +const Label = styled.label` + margin-bottom: 0.5rem; + font-weight: bold; +`; + +const FlexContainer = styled.div` + display: flex; + flex-direction: row; + gap: 10px; + align-items: center; +`; diff --git a/apps/dapp/src/constants/env/local.tsx b/apps/dapp/src/constants/env/local.tsx index b8e596c50..f60600091 100644 --- a/apps/dapp/src/constants/env/local.tsx +++ b/apps/dapp/src/constants/env/local.tsx @@ -127,6 +127,16 @@ const env: Environment = { enableAscend: true, }, templeMultisig: '0x3a320fF715dCBbF097e15257B7051dd08fdfb7A2', + safes: [ + // { + // name: 'Multisig Temple V2', + // address: 'sep:0x7d1e9012aA41278349791f29C2cdaa3DF4ceDcEd', + // }, + // { + // name: 'Multisig Test Fostrich', + // address: '0x5CE28cAE5aAb002DcBc076d5A551A473a7C9dF89', + // }, + ] }; export default env; diff --git a/apps/dapp/src/constants/env/preview.tsx b/apps/dapp/src/constants/env/preview.tsx index 18647411f..629379a9f 100644 --- a/apps/dapp/src/constants/env/preview.tsx +++ b/apps/dapp/src/constants/env/preview.tsx @@ -135,6 +135,16 @@ const env: Environment = { enableAscend: true, }, templeMultisig: '0x3a320fF715dCBbF097e15257B7051dd08fdfb7A2', + safes: [ + // { + // name: 'Multisig Temple V2', + // address: '0x7d1e9012aA41278349791f29C2cdaa3DF4ceDcEd', + // }, + // { + // name: 'Multisig Test Fostrich', + // address: '0x5CE28cAE5aAb002DcBc076d5A551A473a7C9dF89', + // }, + ], }; export default env; diff --git a/apps/dapp/src/constants/env/production.tsx b/apps/dapp/src/constants/env/production.tsx index 366cd394d..edd0aa8da 100644 --- a/apps/dapp/src/constants/env/production.tsx +++ b/apps/dapp/src/constants/env/production.tsx @@ -163,6 +163,28 @@ const env: Environment = { api_host: 'https://app.posthog.com', }, templeMultisig: '0xe2Bb722DA825eBfFa1E368De244bdF08ed68B5c4', + safes: [ + // { + // name: 'Ethereum Mainnet Treasury', + // address: '0xb1BD5762fAf7D6F86f965a3fF324BD81bB746d00', + // }, + // { + // name: 'DAO Runway', + // address: '0x4D6175d58C5AceEf30F546C0d5A557efFa53A950', + // }, + // { + // name: 'OLB:', + // address: '0x5C8898f8E0F9468D4A677887bC03EE2659321012', + // }, + // { + // name: 'Temple Executors', + // address: '0x94b62A27a2f23CBdc0220826a8452fB5055cF273', + // }, + // { + // name: 'Temple Rescuers', + // address: '0x9f90430179D9b67341BFa50559bc7B8E35629f1b', + // }, + ], }; export default env; diff --git a/apps/dapp/src/constants/env/types.ts b/apps/dapp/src/constants/env/types.ts index 21cbf21fa..acddeb6e4 100644 --- a/apps/dapp/src/constants/env/types.ts +++ b/apps/dapp/src/constants/env/types.ts @@ -88,6 +88,11 @@ interface Posthog { api_host: string; } +export interface SafeWallet { + name: string; + address: string; +} + export interface Environment { alchemyId: string; rpcUrl: string; @@ -108,4 +113,5 @@ export interface Environment { featureFlags: { enableAscend: boolean; }; + safes: SafeWallet[]; } diff --git a/apps/dapp/src/hooks/use-geo-blocked.tsx b/apps/dapp/src/hooks/use-geo-blocked.tsx index cc8bac028..1886a96c4 100644 --- a/apps/dapp/src/hooks/use-geo-blocked.tsx +++ b/apps/dapp/src/hooks/use-geo-blocked.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'; export const useGeoBlocked = () => { const [isBlocked, setIsBlocked] = useState(false); const [loading, setLoading] = useState(true); + const IS_DEVELOPMENT = import.meta.env.MODE == 'development'; useEffect(() => { const checkBlocked = async () => { @@ -11,7 +12,8 @@ export const useGeoBlocked = () => { .then((res) => res.blocked) .catch((err: unknown) => { console.log('geoblock error:', err); - return false; + if (IS_DEVELOPMENT) return false; // don't block users on dev + return true; }); setIsBlocked(blocked); setLoading(false); diff --git a/apps/dapp/src/main.tsx b/apps/dapp/src/main.tsx index c24588db2..e2aabf947 100644 --- a/apps/dapp/src/main.tsx +++ b/apps/dapp/src/main.tsx @@ -11,7 +11,6 @@ import Loader from 'components/Loader/Loader'; import Disclaimer from 'components/Pages/Disclaimer'; import Home from 'components/Pages/Core/NewUI/Home'; -import env from 'constants/env'; import { AnalyticsService } from 'services/AnalyticsService'; import { DashboardPage } from 'components/Pages/Core/DappPages/Dashboard'; import { TradePage } from './components/Pages/Core/DappPages/TradePage'; @@ -23,6 +22,7 @@ import { OhmagePage } from 'components/Pages/Core/DappPages/OhmagePage'; // Separate Chunks const TeamPayments = React.lazy(() => import('components/Pages/TeamPayments')); const RamosAdmin = React.lazy(() => import('components/Pages/Ramos/admin')); +const SafeAdmin = React.lazy(() => import('components/Pages/Safe/admin')); const LoaderWrapper = styled.div` display: flex; @@ -66,6 +66,7 @@ ReactDOM.render( } /> } /> } /> + } /> }> } /> diff --git a/apps/dapp/src/safe/open-api/.gitignore b/apps/dapp/src/safe/open-api/.gitignore new file mode 100644 index 000000000..2a11f8b95 --- /dev/null +++ b/apps/dapp/src/safe/open-api/.gitignore @@ -0,0 +1 @@ +client \ No newline at end of file diff --git a/apps/dapp/src/safe/open-api/apiV1.json b/apps/dapp/src/safe/open-api/apiV1.json new file mode 100644 index 000000000..afa6edca2 --- /dev/null +++ b/apps/dapp/src/safe/open-api/apiV1.json @@ -0,0 +1,3956 @@ +{ + "swagger": "2.0", + "info": { + "title": "Safe Transaction Service API", + "description": "API to keep track of transactions sent via Safe smart contracts", + "license": { + "name": "MIT License" + }, + "version": "v1" + }, + "host": "safe-transaction-sepolia.safe.global", + "schemes": ["https"], + "basePath": "/api", + "consumes": ["application/json"], + "produces": ["application/json"], + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + }, + "security": [ + { + "api_key": [] + } + ], + "paths": { + "/v1/about/": { + "get": { + "operationId": "v1_about_list", + "description": "Returns information and configuration of the service", + "parameters": [], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/about/ethereum-rpc/": { + "get": { + "operationId": "v1_about_ethereum-rpc_list", + "description": "Get information about the Ethereum RPC node used by the service", + "parameters": [], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/about/ethereum-tracing-rpc/": { + "get": { + "operationId": "v1_about_ethereum-tracing-rpc_list", + "description": "Get information about the Ethereum Tracing RPC node used by the service (if any configured)", + "parameters": [], + "responses": { + "200": { + "description": "" + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/about/indexing/": { + "get": { + "operationId": "v1_about_indexing_list", + "description": "Get current indexing status for ERC20/721 events", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/IndexingStatus" + } + } + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/about/master-copies/": { + "get": { + "operationId": "v1_about_master-copies_list", + "description": "Use `singletons` instead of `master-copies`", + "parameters": [], + "responses": { + "200": { + "description": "Ok" + } + }, + "tags": ["v1"], + "deprecated": true + }, + "parameters": [] + }, + "/v1/about/singletons/": { + "get": { + "operationId": "v1_about_singletons_list", + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/MasterCopyResponse" + } + } + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/contracts/": { + "get": { + "operationId": "v1_contracts_list", + "description": "", + "parameters": [ + { + "name": "ordering", + "in": "query", + "description": "Which field to use when ordering the results.", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "required": ["count", "results"], + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "next": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "previous": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/definitions/Contract" + } + } + } + } + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/contracts/{address}/": { + "get": { + "operationId": "v1_contracts_read", + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/Contract" + } + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "description": "A unique value identifying this contract.", + "required": true, + "type": "string" + } + ] + }, + "/v1/data-decoder/": { + "post": { + "operationId": "v1_data-decoder_create", + "description": "Returns decoded information using tx service internal ABI information given the tx\ndata as a `0x` prefixed hexadecimal string.\nIf address of the receiving contract is provided decoded data will be more accurate,\nas in case of ABI collision service will know which ABI to use.", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DataDecoder" + } + } + ], + "responses": { + "200": { + "description": "Decoded data" + }, + "404": { + "description": "Cannot find function selector to decode data" + }, + "422": { + "description": "Invalid data" + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/delegates/": { + "get": { + "operationId": "v1_delegates_list", + "description": "Get list of delegates", + "parameters": [ + { + "name": "safe", + "in": "query", + "description": "safe", + "required": false, + "type": "string" + }, + { + "name": "delegate", + "in": "query", + "description": "delegate", + "required": false, + "type": "string" + }, + { + "name": "delegator", + "in": "query", + "description": "delegator", + "required": false, + "type": "string" + }, + { + "name": "label", + "in": "query", + "description": "label", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "required": ["count", "results"], + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "next": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "previous": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeDelegateResponse" + } + } + } + } + }, + "400": { + "description": "Invalid data" + } + }, + "tags": ["v1"] + }, + "post": { + "operationId": "v1_delegates_create", + "description": "Create a delegate for a Safe address with a custom label. Calls with same delegate but different label or\nsigner will update the label or delegator if different.\nFor the signature we are using TOTP with `T0=0` and `Tx=3600`. TOTP is calculated by taking the\nUnix UTC epoch time (no milliseconds) and dividing by 3600 (natural division, no decimals)\nFor signature this hash need to be signed: keccak(checksummed address + str(int(current_epoch // 3600)))\nFor example:\n - We want to add the delegate `0x132512f995866CcE1b0092384A6118EDaF4508Ff` and `epoch=1586779140`.\n - `TOTP = epoch // 3600 = 1586779140 // 3600 = 440771`\n - The hash to sign by a Safe owner would be `keccak(\"0x132512f995866CcE1b0092384A6118EDaF4508Ff440771\")`", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Delegate" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "description": "Malformed data" + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/delegates/{delegate_address}/": { + "delete": { + "operationId": "v1_delegates_delete", + "description": "Delete every pair delegate/delegator found. Signature is built the same way as for adding a delegate,\nbut in this case the signer can be either the `delegator` (owner) or the `delegate` itself.\nCheck `POST /delegates/`", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DelegateDelete" + } + } + ], + "responses": { + "204": { + "description": "Deleted" + }, + "400": { + "description": "Malformed data" + }, + "404": { + "description": "Delegate not found" + }, + "422": { + "description": "Invalid Ethereum address/Error processing data" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "delegate_address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/messages/{message_hash}/": { + "get": { + "operationId": "v1_messages_read", + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/SafeMessageResponse" + } + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "message_hash", + "in": "path", + "description": "A unique value identifying this safe message.", + "required": true, + "type": "string", + "format": "binary" + } + ] + }, + "/v1/messages/{message_hash}/signatures/": { + "post": { + "operationId": "v1_messages_signatures_create", + "description": "", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/SafeMessageSignature" + } + } + ], + "responses": { + "201": { + "description": "Created" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "message_hash", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/module-transaction/{module_transaction_id}": { + "get": { + "operationId": "v1_module-transaction_read", + "description": ":return: module transaction filtered by module_transaction_id", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/SafeModuleTransactionResponse" + } + }, + "404": { + "description": "ModuleTransaction does not exist" + }, + "400": { + "description": "Invalid moduleTransactionId" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "module_transaction_id", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/modules/{address}/safes/": { + "get": { + "operationId": "v1_modules_safes_list", + "description": "Return Safes where the module address provided is enabled", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/ModulesResponse" + } + }, + "422": { + "description": "Module address checksum not valid" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/multisig-transactions/{safe_tx_hash}/": { + "get": { + "operationId": "v1_multisig-transactions_read", + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/SafeMultisigTransactionResponse" + } + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "safe_tx_hash", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/multisig-transactions/{safe_tx_hash}/confirmations/": { + "get": { + "operationId": "v1_multisig-transactions_confirmations_list", + "description": "Get the list of confirmations for a multisig transaction", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "required": ["count", "results"], + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "next": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "previous": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeMultisigConfirmationResponse" + } + } + } + } + }, + "400": { + "description": "Invalid data" + } + }, + "tags": ["v1"] + }, + "post": { + "operationId": "v1_multisig-transactions_confirmations_create", + "description": "Add a confirmation for a transaction. More than one signature can be used. This endpoint does not support\nthe use of delegates to make a transaction trusted.", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/SafeMultisigConfirmation" + } + } + ], + "responses": { + "201": { + "description": "Created" + }, + "400": { + "description": "Malformed data" + }, + "422": { + "description": "Error processing data" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "safe_tx_hash", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/notifications/devices/": { + "post": { + "operationId": "v1_notifications_devices_create", + "description": "Creates a new FirebaseDevice. If uuid is not provided a new device will be created.\nIf a uuid for an existing Safe is provided the FirebaseDevice will be updated with all the new data provided.\nSafes provided on the request are always added and never removed/replaced\nSignature must sign `keccack256('gnosis-safe{timestamp-epoch}{uuid}{cloud_messaging_token}{safes_sorted}':\n - `{timestamp-epoch}` must be an integer (no milliseconds)\n - `{safes_sorted}` must be checksummed safe addresses sorted and joined with no spaces", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/FirebaseDevice" + } + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/FirebaseDeviceSerializerWithOwnersResponse" + } + }, + "400": { + "description": "Invalid data" + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/notifications/devices/{uuid}/": { + "delete": { + "operationId": "v1_notifications_devices_delete", + "description": "Remove a FirebaseDevice", + "parameters": [], + "responses": { + "204": { + "description": "" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "A UUID string identifying this Firebase Device.", + "required": true, + "type": "string", + "format": "uuid" + } + ] + }, + "/v1/notifications/devices/{uuid}/safes/{address}/": { + "delete": { + "operationId": "v1_notifications_devices_safes_delete", + "description": "Remove a Safe for a FirebaseDevice", + "parameters": [], + "responses": { + "204": { + "description": "" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "uuid", + "in": "path", + "description": "A UUID string identifying this Firebase Device.", + "required": true, + "type": "string", + "format": "uuid" + }, + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/owners/{address}/safes/": { + "get": { + "operationId": "v1_owners_safes_list", + "description": "Return Safes where the address provided is an owner", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/OwnerResponse" + } + }, + "422": { + "description": "Owner address checksum not valid" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/": { + "get": { + "operationId": "v1_safes_read", + "description": "Get status of the safe", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/SafeInfoResponse" + } + }, + "404": { + "description": "Safe not found" + }, + "422": { + "description": "code = 1: Checksum address validation failed\ncode = 50: Cannot get Safe info" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/all-transactions/": { + "get": { + "operationId": "v1_safes_all-transactions_list", + "description": "Returns a paginated list of transactions for a Safe. The list has different structures depending on the\ntransaction type:\n- Multisig Transactions for a Safe. `tx_type=MULTISIG_TRANSACTION`. If the query parameter `queued=False` is\nset only the transactions with `safe nonce < current Safe nonce` will be displayed. By default, only the\n`trusted` transactions will be displayed (transactions indexed, with at least one confirmation or proposed\nby a delegate). If you need that behaviour to be disabled set the query parameter `trusted=False`\n- Module Transactions for a Safe. `tx_type=MODULE_TRANSACTION`\n- Incoming Transfers of Ether/ERC20 Tokens/ERC721 Tokens. `tx_type=ETHEREUM_TRANSACTION`", + "parameters": [ + { + "name": "ordering", + "in": "query", + "description": "Which field to use when ordering the results.", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + }, + { + "name": "executed", + "in": "query", + "description": "If `True` only executed transactions are returned", + "type": "boolean", + "default": false + }, + { + "name": "queued", + "in": "query", + "description": "If `True` transactions with `nonce >= Safe current nonce` are also returned", + "type": "boolean", + "default": true + }, + { + "name": "trusted", + "in": "query", + "description": "If `True` just trusted transactions are shown (indexed, added by a delegate or with at least one confirmation)", + "type": "boolean", + "default": true + } + ], + "responses": { + "200": { + "description": "A list with every element with the structure of one of these transactiontypes", + "schema": { + "required": ["count", "results"], + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "next": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "previous": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/definitions/AllTransactionsSchema" + } + } + } + } + }, + "422": { + "description": "code = 1: Checksum address validation failed" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/balances/": { + "get": { + "operationId": "v1_safes_balances_list", + "description": "Get balance for Ether and ERC20 tokens", + "parameters": [ + { + "name": "trusted", + "in": "query", + "description": "If `True` just trusted tokens will be returned", + "type": "boolean", + "default": false + }, + { + "name": "exclude_spam", + "in": "query", + "description": "If `True` spam tokens will not be returned", + "type": "boolean", + "default": false + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeBalanceResponse" + } + } + }, + "404": { + "description": "Safe not found" + }, + "422": { + "description": "Safe address checksum not valid" + } + }, + "tags": ["v1"], + "deprecated": false + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/balances/usd/": { + "get": { + "operationId": "v1_safes_balances_usd_list", + "description": "Get balance for Ether and ERC20 tokens with USD fiat conversion", + "parameters": [ + { + "name": "trusted", + "in": "query", + "description": "If `True` just trusted tokens will be returned", + "type": "boolean", + "default": false + }, + { + "name": "exclude_spam", + "in": "query", + "description": "If `True` spam tokens will not be returned", + "type": "boolean", + "default": false + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeBalanceUsdResponse" + } + } + }, + "404": { + "description": "Safe not found" + }, + "422": { + "description": "Safe address checksum not valid" + } + }, + "tags": ["v1"], + "deprecated": false + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/creation/": { + "get": { + "operationId": "v1_safes_creation_list", + "description": "Get status of the safe", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/SafeCreationInfoResponse" + } + }, + "404": { + "description": "Safe creation not found" + }, + "422": { + "description": "Owner address checksum not valid" + }, + "503": { + "description": "Problem connecting to Ethereum network" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/delegates/{delegate_address}/": { + "delete": { + "operationId": "v1_safes_delegates_delete", + "description": "Delete a delegate for a Safe. Signature is built the same way that for adding a delegate.\nCheck `POST /delegates/`", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/SafeDelegateDelete" + } + } + ], + "responses": { + "204": { + "description": "Deleted" + }, + "400": { + "description": "Malformed data" + }, + "404": { + "description": "Delegate not found" + }, + "422": { + "description": "Invalid Ethereum address/Error processing data" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "delegate_address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/incoming-transfers/": { + "get": { + "operationId": "v1_safes_incoming-transfers_list", + "description": "Returns incoming ether/tokens transfers for a Safe", + "parameters": [ + { + "name": "_from", + "in": "query", + "description": "_from", + "required": false, + "type": "string" + }, + { + "name": "block_number", + "in": "query", + "description": "block_number", + "required": false, + "type": "string" + }, + { + "name": "block_number__gt", + "in": "query", + "description": "block_number__gt", + "required": false, + "type": "string" + }, + { + "name": "block_number__lt", + "in": "query", + "description": "block_number__lt", + "required": false, + "type": "string" + }, + { + "name": "execution_date__gte", + "in": "query", + "description": "execution_date__gte", + "required": false, + "type": "string" + }, + { + "name": "execution_date__lte", + "in": "query", + "description": "execution_date__lte", + "required": false, + "type": "string" + }, + { + "name": "execution_date__gt", + "in": "query", + "description": "execution_date__gt", + "required": false, + "type": "string" + }, + { + "name": "execution_date__lt", + "in": "query", + "description": "execution_date__lt", + "required": false, + "type": "string" + }, + { + "name": "to", + "in": "query", + "description": "to", + "required": false, + "type": "string" + }, + { + "name": "token_address", + "in": "query", + "description": "token_address", + "required": false, + "type": "string" + }, + { + "name": "transaction_hash", + "in": "query", + "description": "transaction_hash", + "required": false, + "type": "string" + }, + { + "name": "value", + "in": "query", + "description": "value", + "required": false, + "type": "string" + }, + { + "name": "value__gt", + "in": "query", + "description": "value__gt", + "required": false, + "type": "string" + }, + { + "name": "value__lt", + "in": "query", + "description": "value__lt", + "required": false, + "type": "string" + }, + { + "name": "erc20", + "in": "query", + "description": "erc20", + "required": false, + "type": "string" + }, + { + "name": "erc721", + "in": "query", + "description": "erc721", + "required": false, + "type": "string" + }, + { + "name": "ether", + "in": "query", + "description": "ether", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/TransferWithTokenInfoResponse" + } + } + }, + "422": { + "description": "Safe address checksum not valid" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/messages/": { + "get": { + "operationId": "v1_safes_messages_list", + "description": "", + "parameters": [ + { + "name": "ordering", + "in": "query", + "description": "Which field to use when ordering the results.", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "required": ["count", "results"], + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "next": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "previous": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeMessageResponse" + } + } + } + } + } + }, + "tags": ["v1"] + }, + "post": { + "operationId": "v1_safes_messages_create", + "description": "Create a new signed message for a Safe. Message can be:\n- A ``string``, so ``EIP191`` will be used to get the hash.\n- An ``EIP712`` ``object``.\n\nHash will be calculated from the provided ``message``. Sending a raw ``hash`` will not be accepted,\nservice needs to derive it itself.", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/SafeMessage" + } + } + ], + "responses": { + "201": { + "description": "Created" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/module-transactions/": { + "get": { + "operationId": "v1_safes_module-transactions_list", + "description": "Returns the module transaction of a Safe", + "parameters": [ + { + "name": "safe", + "in": "query", + "description": "safe", + "required": false, + "type": "string" + }, + { + "name": "module", + "in": "query", + "description": "module", + "required": false, + "type": "string" + }, + { + "name": "to", + "in": "query", + "description": "to", + "required": false, + "type": "string" + }, + { + "name": "operation", + "in": "query", + "description": "operation", + "required": false, + "type": "string", + "enum": [0, 1, 2] + }, + { + "name": "failed", + "in": "query", + "description": "failed", + "required": false, + "type": "string" + }, + { + "name": "block_number", + "in": "query", + "description": "block_number", + "required": false, + "type": "string" + }, + { + "name": "block_number__gt", + "in": "query", + "description": "block_number__gt", + "required": false, + "type": "string" + }, + { + "name": "block_number__lt", + "in": "query", + "description": "block_number__lt", + "required": false, + "type": "string" + }, + { + "name": "transaction_hash", + "in": "query", + "description": "transaction_hash", + "required": false, + "type": "string" + }, + { + "name": "ordering", + "in": "query", + "description": "Which field to use when ordering the results.", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "required": ["count", "results"], + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "next": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "previous": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeModuleTransactionResponse" + } + } + } + } + }, + "400": { + "description": "Invalid data" + }, + "422": { + "description": "Invalid ethereum address" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/multisig-transactions/": { + "get": { + "operationId": "v1_safes_multisig-transactions_list", + "description": "Returns the history of a multisig tx (safe)", + "parameters": [ + { + "name": "failed", + "in": "query", + "description": "failed", + "required": false, + "type": "string" + }, + { + "name": "modified__lt", + "in": "query", + "description": "modified__lt", + "required": false, + "type": "string" + }, + { + "name": "modified__gt", + "in": "query", + "description": "modified__gt", + "required": false, + "type": "string" + }, + { + "name": "modified__lte", + "in": "query", + "description": "modified__lte", + "required": false, + "type": "string" + }, + { + "name": "modified__gte", + "in": "query", + "description": "modified__gte", + "required": false, + "type": "string" + }, + { + "name": "nonce__lt", + "in": "query", + "description": "nonce__lt", + "required": false, + "type": "string" + }, + { + "name": "nonce__gt", + "in": "query", + "description": "nonce__gt", + "required": false, + "type": "string" + }, + { + "name": "nonce__lte", + "in": "query", + "description": "nonce__lte", + "required": false, + "type": "string" + }, + { + "name": "nonce__gte", + "in": "query", + "description": "nonce__gte", + "required": false, + "type": "string" + }, + { + "name": "nonce", + "in": "query", + "description": "nonce", + "required": false, + "type": "string" + }, + { + "name": "safe_tx_hash", + "in": "query", + "description": "safe_tx_hash", + "required": false, + "type": "string" + }, + { + "name": "to", + "in": "query", + "description": "to", + "required": false, + "type": "string" + }, + { + "name": "value__lt", + "in": "query", + "description": "value__lt", + "required": false, + "type": "string" + }, + { + "name": "value__gt", + "in": "query", + "description": "value__gt", + "required": false, + "type": "string" + }, + { + "name": "value", + "in": "query", + "description": "value", + "required": false, + "type": "string" + }, + { + "name": "executed", + "in": "query", + "description": "executed", + "required": false, + "type": "string" + }, + { + "name": "has_confirmations", + "in": "query", + "description": "has_confirmations", + "required": false, + "type": "string" + }, + { + "name": "trusted", + "in": "query", + "description": "trusted", + "required": false, + "type": "string" + }, + { + "name": "execution_date__gte", + "in": "query", + "description": "execution_date__gte", + "required": false, + "type": "string" + }, + { + "name": "execution_date__lte", + "in": "query", + "description": "execution_date__lte", + "required": false, + "type": "string" + }, + { + "name": "submission_date__gte", + "in": "query", + "description": "submission_date__gte", + "required": false, + "type": "string" + }, + { + "name": "submission_date__lte", + "in": "query", + "description": "submission_date__lte", + "required": false, + "type": "string" + }, + { + "name": "transaction_hash", + "in": "query", + "description": "transaction_hash", + "required": false, + "type": "string" + }, + { + "name": "ordering", + "in": "query", + "description": "Which field to use when ordering the results.", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "required": ["count", "results"], + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "next": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "previous": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeMultisigTransactionResponse" + } + } + } + } + }, + "400": { + "description": "Invalid data" + }, + "422": { + "description": "Invalid ethereum address" + } + }, + "tags": ["v1"] + }, + "post": { + "operationId": "v1_safes_multisig-transactions_create", + "description": "Creates a Multisig Transaction with its confirmations and retrieves all the information related.", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/SafeMultisigTransaction" + } + } + ], + "responses": { + "201": { + "description": "Created or signature updated" + }, + "400": { + "description": "Invalid data" + }, + "422": { + "description": "Invalid ethereum address/User is not an owner/Invalid safeTxHash/Invalid signature/Nonce already executed/Sender is not an owner" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/multisig-transactions/estimations/": { + "post": { + "operationId": "v1_safes_multisig-transactions_estimations_create", + "description": "Estimates `safeTxGas` for a Safe Multisig Transaction.", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/SafeMultisigTransactionEstimate" + } + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/SafeMultisigTransactionEstimateResponse" + } + }, + "400": { + "description": "Data not valid" + }, + "404": { + "description": "Safe not found" + }, + "422": { + "description": "Tx not valid" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/transactions/": { + "get": { + "operationId": "v1_safes_transactions_list", + "description": "Use `multisig-transactions` instead of `transactions`", + "parameters": [ + { + "name": "failed", + "in": "query", + "description": "failed", + "required": false, + "type": "string" + }, + { + "name": "modified__lt", + "in": "query", + "description": "modified__lt", + "required": false, + "type": "string" + }, + { + "name": "modified__gt", + "in": "query", + "description": "modified__gt", + "required": false, + "type": "string" + }, + { + "name": "modified__lte", + "in": "query", + "description": "modified__lte", + "required": false, + "type": "string" + }, + { + "name": "modified__gte", + "in": "query", + "description": "modified__gte", + "required": false, + "type": "string" + }, + { + "name": "nonce__lt", + "in": "query", + "description": "nonce__lt", + "required": false, + "type": "string" + }, + { + "name": "nonce__gt", + "in": "query", + "description": "nonce__gt", + "required": false, + "type": "string" + }, + { + "name": "nonce__lte", + "in": "query", + "description": "nonce__lte", + "required": false, + "type": "string" + }, + { + "name": "nonce__gte", + "in": "query", + "description": "nonce__gte", + "required": false, + "type": "string" + }, + { + "name": "nonce", + "in": "query", + "description": "nonce", + "required": false, + "type": "string" + }, + { + "name": "safe_tx_hash", + "in": "query", + "description": "safe_tx_hash", + "required": false, + "type": "string" + }, + { + "name": "to", + "in": "query", + "description": "to", + "required": false, + "type": "string" + }, + { + "name": "value__lt", + "in": "query", + "description": "value__lt", + "required": false, + "type": "string" + }, + { + "name": "value__gt", + "in": "query", + "description": "value__gt", + "required": false, + "type": "string" + }, + { + "name": "value", + "in": "query", + "description": "value", + "required": false, + "type": "string" + }, + { + "name": "executed", + "in": "query", + "description": "executed", + "required": false, + "type": "string" + }, + { + "name": "has_confirmations", + "in": "query", + "description": "has_confirmations", + "required": false, + "type": "string" + }, + { + "name": "trusted", + "in": "query", + "description": "trusted", + "required": false, + "type": "string" + }, + { + "name": "execution_date__gte", + "in": "query", + "description": "execution_date__gte", + "required": false, + "type": "string" + }, + { + "name": "execution_date__lte", + "in": "query", + "description": "execution_date__lte", + "required": false, + "type": "string" + }, + { + "name": "submission_date__gte", + "in": "query", + "description": "submission_date__gte", + "required": false, + "type": "string" + }, + { + "name": "submission_date__lte", + "in": "query", + "description": "submission_date__lte", + "required": false, + "type": "string" + }, + { + "name": "transaction_hash", + "in": "query", + "description": "transaction_hash", + "required": false, + "type": "string" + }, + { + "name": "ordering", + "in": "query", + "description": "Which field to use when ordering the results.", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "required": ["count", "results"], + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "next": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "previous": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeMultisigTransactionResponse" + } + } + } + } + } + }, + "tags": ["v1"], + "deprecated": true + }, + "post": { + "operationId": "v1_safes_transactions_create", + "description": "Use `multisig-transactions` instead of `transactions`", + "parameters": [ + { + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/SafeMultisigTransaction" + } + } + ], + "responses": { + "201": { + "description": "", + "schema": { + "$ref": "#/definitions/SafeMultisigTransaction" + } + } + }, + "tags": ["v1"], + "deprecated": true + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/safes/{address}/transfers/": { + "get": { + "operationId": "v1_safes_transfers_list", + "description": "Returns ether/tokens transfers for a Safe", + "parameters": [ + { + "name": "_from", + "in": "query", + "description": "_from", + "required": false, + "type": "string" + }, + { + "name": "block_number", + "in": "query", + "description": "block_number", + "required": false, + "type": "string" + }, + { + "name": "block_number__gt", + "in": "query", + "description": "block_number__gt", + "required": false, + "type": "string" + }, + { + "name": "block_number__lt", + "in": "query", + "description": "block_number__lt", + "required": false, + "type": "string" + }, + { + "name": "execution_date__gte", + "in": "query", + "description": "execution_date__gte", + "required": false, + "type": "string" + }, + { + "name": "execution_date__lte", + "in": "query", + "description": "execution_date__lte", + "required": false, + "type": "string" + }, + { + "name": "execution_date__gt", + "in": "query", + "description": "execution_date__gt", + "required": false, + "type": "string" + }, + { + "name": "execution_date__lt", + "in": "query", + "description": "execution_date__lt", + "required": false, + "type": "string" + }, + { + "name": "to", + "in": "query", + "description": "to", + "required": false, + "type": "string" + }, + { + "name": "token_address", + "in": "query", + "description": "token_address", + "required": false, + "type": "string" + }, + { + "name": "transaction_hash", + "in": "query", + "description": "transaction_hash", + "required": false, + "type": "string" + }, + { + "name": "value", + "in": "query", + "description": "value", + "required": false, + "type": "string" + }, + { + "name": "value__gt", + "in": "query", + "description": "value__gt", + "required": false, + "type": "string" + }, + { + "name": "value__lt", + "in": "query", + "description": "value__lt", + "required": false, + "type": "string" + }, + { + "name": "erc20", + "in": "query", + "description": "erc20", + "required": false, + "type": "string" + }, + { + "name": "erc721", + "in": "query", + "description": "erc721", + "required": false, + "type": "string" + }, + { + "name": "ether", + "in": "query", + "description": "ether", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/TransferWithTokenInfoResponse" + } + } + }, + "422": { + "description": "Safe address checksum not valid" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/tokens/": { + "get": { + "operationId": "v1_tokens_list", + "description": "", + "parameters": [ + { + "name": "name", + "in": "query", + "description": "name", + "required": false, + "type": "string" + }, + { + "name": "address", + "in": "query", + "description": "address", + "required": false, + "type": "string" + }, + { + "name": "symbol", + "in": "query", + "description": "symbol", + "required": false, + "type": "string" + }, + { + "name": "decimals__lt", + "in": "query", + "description": "decimals__lt", + "required": false, + "type": "string" + }, + { + "name": "decimals__gt", + "in": "query", + "description": "decimals__gt", + "required": false, + "type": "string" + }, + { + "name": "decimals", + "in": "query", + "description": "decimals", + "required": false, + "type": "string" + }, + { + "name": "search", + "in": "query", + "description": "A search term.", + "required": false, + "type": "string" + }, + { + "name": "ordering", + "in": "query", + "description": "Which field to use when ordering the results.", + "required": false, + "type": "string" + }, + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "required": ["count", "results"], + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "next": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "previous": { + "type": "string", + "format": "uri", + "x-nullable": true + }, + "results": { + "type": "array", + "items": { + "$ref": "#/definitions/TokenInfoResponse" + } + } + } + } + } + }, + "tags": ["v1"] + }, + "parameters": [] + }, + "/v1/tokens/{address}/": { + "get": { + "operationId": "v1_tokens_read", + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/TokenInfoResponse" + } + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "address", + "in": "path", + "description": "A unique value identifying this token.", + "required": true, + "type": "string" + } + ] + }, + "/v1/transactions/{safe_tx_hash}/": { + "get": { + "operationId": "v1_transactions_read", + "description": "Use `multisig-transactions` instead of `transactions`", + "parameters": [], + "responses": { + "200": { + "description": "Ok" + }, + "404": { + "description": "Not found" + } + }, + "tags": ["v1"], + "deprecated": true + }, + "parameters": [ + { + "name": "safe_tx_hash", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v1/transfer/{transfer_id}": { + "get": { + "operationId": "v1_transfer_read", + "description": ":return: transfer filtered by transfer_id", + "parameters": [], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/TransferWithTokenInfoResponse" + } + }, + "404": { + "description": "Transfer does not exist" + }, + "400": { + "description": "Invalid transferId" + } + }, + "tags": ["v1"] + }, + "parameters": [ + { + "name": "transfer_id", + "in": "path", + "required": true, + "type": "string" + } + ] + }, + "/v2/safes/{address}/collectibles/": { + "get": { + "operationId": "v2_safes_collectibles_list", + "description": "Get collectibles (ERC721 tokens) and information about them", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Number of results to return per page.", + "required": false, + "type": "integer" + }, + { + "name": "offset", + "in": "query", + "description": "The initial index from which to return the results.", + "required": false, + "type": "integer" + }, + { + "name": "trusted", + "in": "query", + "description": "If `True` just trusted tokens will be returned", + "type": "boolean", + "default": false + }, + { + "name": "exclude_spam", + "in": "query", + "description": "If `True` spam tokens will not be returned", + "type": "boolean", + "default": false + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeCollectibleResponse" + } + } + }, + "404": { + "description": "Safe not found" + }, + "422": { + "description": "Safe address checksum not valid" + } + }, + "tags": ["v2"], + "deprecated": false + }, + "parameters": [ + { + "name": "address", + "in": "path", + "required": true, + "type": "string" + } + ] + } + }, + "definitions": { + "IndexingStatus": { + "required": [ + "currentBlockNumber", + "erc20BlockNumber", + "erc20Synced", + "masterCopiesBlockNumber", + "masterCopiesSynced", + "synced" + ], + "type": "object", + "properties": { + "currentBlockNumber": { + "title": "Current block number", + "type": "integer" + }, + "erc20BlockNumber": { + "title": "Erc20 block number", + "type": "integer" + }, + "erc20Synced": { + "title": "Erc20 synced", + "type": "boolean" + }, + "masterCopiesBlockNumber": { + "title": "Master copies block number", + "type": "integer" + }, + "masterCopiesSynced": { + "title": "Master copies synced", + "type": "boolean" + }, + "synced": { + "title": "Synced", + "type": "boolean" + } + } + }, + "MasterCopyResponse": { + "required": ["address", "version", "deployer", "deployedBlockNumber", "lastIndexedBlockNumber", "l2"], + "type": "object", + "properties": { + "address": { + "title": "Address", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string", + "minLength": 1 + }, + "deployer": { + "title": "Deployer", + "type": "string", + "minLength": 1 + }, + "deployedBlockNumber": { + "title": "Deployed block number", + "type": "integer" + }, + "lastIndexedBlockNumber": { + "title": "Last indexed block number", + "type": "integer" + }, + "l2": { + "title": "L2", + "type": "boolean" + } + } + }, + "ContractAbi": { + "required": ["abi", "description", "relevance"], + "type": "object", + "properties": { + "abi": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "type": "string", + "x-nullable": true + } + } + }, + "description": { + "title": "Description", + "type": "string", + "minLength": 1 + }, + "relevance": { + "title": "Relevance", + "type": "integer" + } + } + }, + "Contract": { + "required": ["address", "name", "displayName", "contractAbi", "trustedForDelegateCall"], + "type": "object", + "properties": { + "address": { + "title": "Address", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string", + "minLength": 1 + }, + "displayName": { + "title": "Display name", + "type": "string", + "minLength": 1 + }, + "logoUri": { + "title": "Logo uri", + "type": "string", + "readOnly": true, + "format": "uri" + }, + "contractAbi": { + "$ref": "#/definitions/ContractAbi" + }, + "trustedForDelegateCall": { + "title": "Trusted for delegate call", + "type": "boolean" + } + } + }, + "DataDecoder": { + "required": ["data"], + "type": "object", + "properties": { + "data": { + "title": "Data", + "type": "string" + }, + "to": { + "title": "To", + "type": "string", + "x-nullable": true + } + } + }, + "SafeDelegateResponse": { + "required": ["safe", "delegate", "delegator", "label"], + "type": "object", + "properties": { + "safe": { + "title": "Safe", + "type": "string" + }, + "delegate": { + "title": "Delegate", + "type": "string" + }, + "delegator": { + "title": "Delegator", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string", + "maxLength": 50, + "minLength": 1 + } + } + }, + "Delegate": { + "required": ["delegate", "delegator", "signature", "label"], + "type": "object", + "properties": { + "safe": { + "title": "Safe", + "type": "string", + "x-nullable": true + }, + "delegate": { + "title": "Delegate", + "type": "string" + }, + "delegator": { + "title": "Delegator", + "type": "string" + }, + "signature": { + "title": "Signature", + "type": "string" + }, + "label": { + "title": "Label", + "type": "string", + "maxLength": 50, + "minLength": 1 + } + } + }, + "DelegateDelete": { + "required": ["delegate", "delegator", "signature"], + "type": "object", + "properties": { + "delegate": { + "title": "Delegate", + "type": "string" + }, + "delegator": { + "title": "Delegator", + "type": "string" + }, + "signature": { + "title": "Signature", + "type": "string" + } + } + }, + "SafeMessageResponse": { + "required": ["created", "modified", "safe", "messageHash", "message", "proposedBy", "safeAppId"], + "type": "object", + "properties": { + "created": { + "title": "Created", + "type": "string", + "format": "date-time" + }, + "modified": { + "title": "Modified", + "type": "string", + "format": "date-time" + }, + "safe": { + "title": "Safe", + "type": "string" + }, + "messageHash": { + "title": "Message hash", + "type": "string" + }, + "message": { + "title": "Message", + "type": "object" + }, + "proposedBy": { + "title": "Proposed by", + "type": "string" + }, + "safeAppId": { + "title": "Safe app id", + "type": "integer" + }, + "confirmations": { + "title": "Confirmations", + "type": "string", + "readOnly": true + }, + "preparedSignature": { + "title": "Prepared signature", + "type": "string", + "readOnly": true + } + } + }, + "SafeMessageSignature": { + "required": ["signature"], + "type": "object", + "properties": { + "signature": { + "title": "Signature", + "type": "string" + } + } + }, + "SafeModuleTransactionResponse": { + "required": ["executionDate", "safe", "module", "to", "value", "data", "operation"], + "type": "object", + "properties": { + "created": { + "title": "Created", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "executionDate": { + "title": "Execution date", + "type": "string", + "format": "date-time" + }, + "blockNumber": { + "title": "Block number", + "type": "integer", + "readOnly": true + }, + "isSuccessful": { + "title": "Is successful", + "type": "boolean", + "readOnly": true + }, + "transactionHash": { + "title": "Transaction hash", + "type": "string", + "readOnly": true + }, + "safe": { + "title": "Safe", + "type": "string", + "minLength": 1 + }, + "module": { + "title": "Module", + "type": "string", + "minLength": 1 + }, + "to": { + "title": "To", + "type": "string", + "minLength": 1 + }, + "value": { + "title": "Value", + "type": "string", + "format": "decimal" + }, + "data": { + "title": "Data", + "type": "string", + "x-nullable": true + }, + "operation": { + "title": "Operation", + "type": "integer", + "enum": [0, 1, 2] + }, + "dataDecoded": { + "title": "Data decoded", + "type": "object", + "readOnly": true + }, + "moduleTransactionId": { + "title": "Module transaction id", + "description": "Internally calculated parameter to uniquely identify a moduleTransaction \n`ModuleTransactionId = i+tx_hash+trace_address`", + "type": "string", + "readOnly": true + } + } + }, + "ModulesResponse": { + "required": ["safes"], + "type": "object", + "properties": { + "safes": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "SafeMultisigConfirmationResponse": { + "description": "\nFilters confirmations queryset\n:param obj: MultisigConfirmation instance\n:return: Serialized queryset\n", + "required": ["owner", "submissionDate", "signature"], + "type": "object", + "properties": { + "owner": { + "title": "Owner", + "type": "string", + "minLength": 1 + }, + "submissionDate": { + "title": "Submission date", + "type": "string", + "format": "date-time" + }, + "transactionHash": { + "title": "Transaction hash", + "type": "string", + "readOnly": true + }, + "signature": { + "title": "Signature", + "type": "string" + }, + "signatureType": { + "title": "Signature type", + "type": "string", + "readOnly": true + } + } + }, + "SafeMultisigTransactionResponse": { + "required": [ + "safe", + "to", + "value", + "operation", + "safeTxGas", + "baseGas", + "gasPrice", + "nonce", + "executionDate", + "submissionDate", + "modified", + "transactionHash", + "safeTxHash", + "proposer", + "isExecuted", + "confirmationsRequired", + "trusted" + ], + "type": "object", + "properties": { + "safe": { + "title": "Safe", + "type": "string" + }, + "to": { + "title": "To", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string", + "minLength": 1 + }, + "data": { + "title": "Data", + "type": "string", + "x-nullable": true + }, + "operation": { + "title": "Operation", + "type": "integer", + "minimum": 0 + }, + "gasToken": { + "title": "Gas token", + "type": "string", + "x-nullable": true + }, + "safeTxGas": { + "title": "Safe tx gas", + "type": "integer", + "minimum": 0 + }, + "baseGas": { + "title": "Base gas", + "type": "integer", + "minimum": 0 + }, + "gasPrice": { + "title": "Gas price", + "type": "string", + "minLength": 1 + }, + "refundReceiver": { + "title": "Refund receiver", + "type": "string", + "x-nullable": true + }, + "nonce": { + "title": "Nonce", + "type": "integer", + "minimum": 0 + }, + "executionDate": { + "title": "Execution date", + "type": "string", + "format": "date-time" + }, + "submissionDate": { + "title": "Submission date", + "type": "string", + "format": "date-time" + }, + "modified": { + "title": "Modified", + "type": "string", + "format": "date-time" + }, + "blockNumber": { + "title": "Block number", + "type": "integer", + "readOnly": true + }, + "transactionHash": { + "title": "Transaction hash", + "type": "string" + }, + "safeTxHash": { + "title": "Safe tx hash", + "type": "string" + }, + "proposer": { + "title": "Proposer", + "type": "string" + }, + "executor": { + "title": "Executor", + "type": "string", + "readOnly": true + }, + "isExecuted": { + "title": "Is executed", + "type": "boolean" + }, + "isSuccessful": { + "title": "Is successful", + "type": "boolean", + "readOnly": true + }, + "ethGasPrice": { + "title": "Eth gas price", + "type": "string", + "readOnly": true + }, + "maxFeePerGas": { + "title": "Max fee per gas", + "type": "string", + "readOnly": true + }, + "maxPriorityFeePerGas": { + "title": "Max priority fee per gas", + "type": "string", + "readOnly": true + }, + "gasUsed": { + "title": "Gas used", + "type": "integer", + "readOnly": true + }, + "fee": { + "title": "Fee", + "type": "integer", + "readOnly": true + }, + "origin": { + "title": "Origin", + "type": "string", + "readOnly": true + }, + "dataDecoded": { + "title": "Data decoded", + "type": "object", + "readOnly": true + }, + "confirmationsRequired": { + "title": "Confirmations required", + "type": "integer" + }, + "confirmations": { + "type": "array", + "items": { + "$ref": "#/definitions/SafeMultisigConfirmationResponse" + } + }, + "trusted": { + "title": "Trusted", + "type": "boolean" + }, + "signatures": { + "title": "Signatures", + "type": "string", + "x-nullable": true + } + } + }, + "SafeMultisigConfirmation": { + "required": ["signature"], + "type": "object", + "properties": { + "signature": { + "title": "Signature", + "type": "string" + } + } + }, + "FirebaseDevice": { + "required": ["safes", "cloudMessagingToken", "buildNumber", "bundle", "deviceType", "version"], + "type": "object", + "properties": { + "uuid": { + "title": "Uuid", + "type": "string", + "format": "uuid", + "default": "acb90cfd-062e-4ae4-9f13-a63939bbfeb2" + }, + "safes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cloudMessagingToken": { + "title": "Cloud messaging token", + "type": "string", + "maxLength": 200, + "minLength": 100 + }, + "buildNumber": { + "title": "Build number", + "type": "integer", + "minimum": 0 + }, + "bundle": { + "title": "Bundle", + "type": "string", + "maxLength": 100, + "minLength": 1 + }, + "deviceType": { + "title": "Device type", + "type": "string", + "enum": ["ANDROID", "IOS", "WEB"] + }, + "version": { + "title": "Version", + "type": "string", + "maxLength": 100, + "minLength": 1 + }, + "timestamp": { + "title": "Timestamp", + "type": "integer" + }, + "signatures": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "FirebaseDeviceSerializerWithOwnersResponse": { + "required": [ + "safes", + "cloudMessagingToken", + "buildNumber", + "bundle", + "deviceType", + "version", + "ownersRegistered", + "ownersNotRegistered" + ], + "type": "object", + "properties": { + "uuid": { + "title": "Uuid", + "type": "string", + "format": "uuid", + "default": "11495275-a7cd-43f3-80b3-37b8caf7f9d2" + }, + "safes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cloudMessagingToken": { + "title": "Cloud messaging token", + "type": "string", + "maxLength": 200, + "minLength": 100 + }, + "buildNumber": { + "title": "Build number", + "type": "integer", + "minimum": 0 + }, + "bundle": { + "title": "Bundle", + "type": "string", + "maxLength": 100, + "minLength": 1 + }, + "deviceType": { + "title": "Device type", + "type": "string", + "enum": ["ANDROID", "IOS", "WEB"] + }, + "version": { + "title": "Version", + "type": "string", + "maxLength": 100, + "minLength": 1 + }, + "timestamp": { + "title": "Timestamp", + "type": "integer" + }, + "signatures": { + "type": "array", + "items": { + "type": "string" + } + }, + "ownersRegistered": { + "type": "array", + "items": { + "type": "string" + } + }, + "ownersNotRegistered": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "OwnerResponse": { + "required": ["safes"], + "type": "object", + "properties": { + "safes": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "SafeInfoResponse": { + "required": [ + "address", + "nonce", + "threshold", + "owners", + "masterCopy", + "modules", + "fallbackHandler", + "guard", + "version" + ], + "type": "object", + "properties": { + "address": { + "title": "Address", + "type": "string" + }, + "nonce": { + "title": "Nonce", + "type": "integer" + }, + "threshold": { + "title": "Threshold", + "type": "integer" + }, + "owners": { + "type": "array", + "items": { + "type": "string" + } + }, + "masterCopy": { + "title": "Master copy", + "type": "string" + }, + "modules": { + "type": "array", + "items": { + "type": "string" + } + }, + "fallbackHandler": { + "title": "Fallback handler", + "type": "string" + }, + "guard": { + "title": "Guard", + "type": "string" + }, + "version": { + "title": "Version", + "type": "string", + "minLength": 1, + "x-nullable": true + } + } + }, + "TokenInfoResponse": { + "required": ["address", "name", "symbol", "decimals", "trusted"], + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "readOnly": true + }, + "address": { + "title": "Address", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string", + "minLength": 1 + }, + "symbol": { + "title": "Symbol", + "type": "string", + "minLength": 1 + }, + "decimals": { + "title": "Decimals", + "type": "integer" + }, + "logoUri": { + "title": "Logo uri", + "type": "string", + "readOnly": true + }, + "trusted": { + "title": "Trusted", + "type": "boolean" + } + } + }, + "TransferWithTokenInfoResponse": { + "required": ["executionDate", "blockNumber", "transactionHash", "to", "value", "tokenId", "tokenInfo", "from"], + "type": "object", + "properties": { + "type": { + "title": "Type", + "type": "string", + "readOnly": true + }, + "executionDate": { + "title": "Execution date", + "type": "string", + "format": "date-time" + }, + "blockNumber": { + "title": "Block number", + "type": "integer" + }, + "transactionHash": { + "title": "Transaction hash", + "type": "string" + }, + "to": { + "title": "To", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string", + "minLength": 1, + "x-nullable": true + }, + "tokenId": { + "title": "Token id", + "type": "string", + "minLength": 1, + "x-nullable": true + }, + "tokenAddress": { + "title": "Token address", + "type": "string", + "x-nullable": true + }, + "transferId": { + "title": "Transfer id", + "description": "Internally calculated parameter to uniquely identify a transfer \nToken transfers are calculated as `transferId = e+tx_hash+log_index` \nEther transfers are calculated as `transferId = i+tx_hash+trace_address`", + "type": "string", + "readOnly": true + }, + "tokenInfo": { + "$ref": "#/definitions/TokenInfoResponse" + }, + "from": { + "title": "From", + "type": "string" + } + } + }, + "SafeModuleTransactionWithTransfersResponse": { + "required": ["executionDate", "safe", "module", "to", "value", "data", "operation", "transfers"], + "type": "object", + "properties": { + "created": { + "title": "Created", + "type": "string", + "format": "date-time", + "readOnly": true + }, + "executionDate": { + "title": "Execution date", + "type": "string", + "format": "date-time" + }, + "blockNumber": { + "title": "Block number", + "type": "integer", + "readOnly": true + }, + "isSuccessful": { + "title": "Is successful", + "type": "boolean", + "readOnly": true + }, + "transactionHash": { + "title": "Transaction hash", + "type": "string", + "readOnly": true + }, + "safe": { + "title": "Safe", + "type": "string", + "minLength": 1 + }, + "module": { + "title": "Module", + "type": "string", + "minLength": 1 + }, + "to": { + "title": "To", + "type": "string", + "minLength": 1 + }, + "value": { + "title": "Value", + "type": "string", + "format": "decimal" + }, + "data": { + "title": "Data", + "type": "string", + "x-nullable": true + }, + "operation": { + "title": "Operation", + "type": "integer", + "enum": [0, 1, 2] + }, + "dataDecoded": { + "title": "Data decoded", + "type": "object", + "readOnly": true + }, + "moduleTransactionId": { + "title": "Module transaction id", + "description": "Internally calculated parameter to uniquely identify a moduleTransaction \n`ModuleTransactionId = i+tx_hash+trace_address`", + "type": "string", + "readOnly": true + }, + "transfers": { + "type": "array", + "items": { + "$ref": "#/definitions/TransferWithTokenInfoResponse" + } + }, + "txType": { + "title": "Tx type", + "type": "string", + "readOnly": true + } + } + }, + "SafeMultisigTransactionWithTransfersResponse": { + "required": [ + "safe", + "to", + "value", + "operation", + "safeTxGas", + "baseGas", + "gasPrice", + "nonce", + "executionDate", + "submissionDate", + "modified", + "transactionHash", + "safeTxHash", + "proposer", + "isExecuted", + "confirmationsRequired", + "trusted", + "transfers" + ], + "type": "object", + "properties": { + "safe": { + "title": "Safe", + "type": "string" + }, + "to": { + "title": "To", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string", + "minLength": 1 + }, + "data": { + "title": "Data", + "type": "string", + "x-nullable": true + }, + "operation": { + "title": "Operation", + "type": "integer", + "minimum": 0 + }, + "gasToken": { + "title": "Gas token", + "type": "string", + "x-nullable": true + }, + "safeTxGas": { + "title": "Safe tx gas", + "type": "integer", + "minimum": 0 + }, + "baseGas": { + "title": "Base gas", + "type": "integer", + "minimum": 0 + }, + "gasPrice": { + "title": "Gas price", + "type": "string", + "minLength": 1 + }, + "refundReceiver": { + "title": "Refund receiver", + "type": "string", + "x-nullable": true + }, + "nonce": { + "title": "Nonce", + "type": "integer", + "minimum": 0 + }, + "executionDate": { + "title": "Execution date", + "type": "string", + "format": "date-time" + }, + "submissionDate": { + "title": "Submission date", + "type": "string", + "format": "date-time" + }, + "modified": { + "title": "Modified", + "type": "string", + "format": "date-time" + }, + "blockNumber": { + "title": "Block number", + "type": "integer", + "readOnly": true + }, + "transactionHash": { + "title": "Transaction hash", + "type": "string" + }, + "safeTxHash": { + "title": "Safe tx hash", + "type": "string" + }, + "proposer": { + "title": "Proposer", + "type": "string" + }, + "executor": { + "title": "Executor", + "type": "string", + "readOnly": true + }, + "isExecuted": { + "title": "Is executed", + "type": "boolean" + }, + "isSuccessful": { + "title": "Is successful", + "type": "boolean", + "readOnly": true + }, + "ethGasPrice": { + "title": "Eth gas price", + "type": "string", + "readOnly": true + }, + "maxFeePerGas": { + "title": "Max fee per gas", + "type": "string", + "readOnly": true + }, + "maxPriorityFeePerGas": { + "title": "Max priority fee per gas", + "type": "string", + "readOnly": true + }, + "gasUsed": { + "title": "Gas used", + "type": "integer", + "readOnly": true + }, + "fee": { + "title": "Fee", + "type": "integer", + "readOnly": true + }, + "origin": { + "title": "Origin", + "type": "string", + "readOnly": true + }, + "dataDecoded": { + "title": "Data decoded", + "type": "object", + "readOnly": true + }, + "confirmationsRequired": { + "title": "Confirmations required", + "type": "integer" + }, + "confirmations": { + "$ref": "#/definitions/SafeMultisigConfirmationResponse" + }, + "trusted": { + "title": "Trusted", + "type": "boolean" + }, + "signatures": { + "title": "Signatures", + "type": "string", + "x-nullable": true + }, + "transfers": { + "type": "array", + "items": { + "$ref": "#/definitions/TransferWithTokenInfoResponse" + } + }, + "txType": { + "title": "Tx type", + "type": "string", + "readOnly": true + } + } + }, + "EthereumTxWithTransfersResponse": { + "required": ["executionDate", "to", "data", "txHash", "transfers", "from"], + "type": "object", + "properties": { + "executionDate": { + "title": "Execution date", + "type": "string", + "format": "date-time" + }, + "to": { + "title": "To", + "type": "string", + "x-nullable": true + }, + "data": { + "title": "Data", + "type": "string" + }, + "txHash": { + "title": "Tx hash", + "type": "string" + }, + "blockNumber": { + "title": "Block number", + "type": "integer", + "readOnly": true + }, + "transfers": { + "type": "array", + "items": { + "$ref": "#/definitions/TransferWithTokenInfoResponse" + } + }, + "txType": { + "title": "Tx type", + "type": "string", + "readOnly": true + }, + "from": { + "title": "From", + "type": "string" + } + } + }, + "AllTransactionsSchema": { + "required": ["txType1", "txType2", "txType3"], + "type": "object", + "properties": { + "txType1": { + "$ref": "#/definitions/SafeModuleTransactionWithTransfersResponse" + }, + "txType2": { + "$ref": "#/definitions/SafeMultisigTransactionWithTransfersResponse" + }, + "txType3": { + "$ref": "#/definitions/EthereumTxWithTransfersResponse" + } + } + }, + "Erc20Info": { + "required": ["name", "symbol", "decimals", "logoUri"], + "type": "object", + "properties": { + "name": { + "title": "Name", + "type": "string", + "minLength": 1 + }, + "symbol": { + "title": "Symbol", + "type": "string", + "minLength": 1 + }, + "decimals": { + "title": "Decimals", + "type": "integer" + }, + "logoUri": { + "title": "Logo uri", + "type": "string", + "minLength": 1 + } + } + }, + "SafeBalanceResponse": { + "required": ["tokenAddress", "token", "balance"], + "type": "object", + "properties": { + "tokenAddress": { + "title": "Token address", + "type": "string", + "minLength": 1 + }, + "token": { + "$ref": "#/definitions/Erc20Info" + }, + "balance": { + "title": "Balance", + "type": "string", + "minLength": 1 + } + } + }, + "SafeBalanceUsdResponse": { + "required": [ + "tokenAddress", + "token", + "balance", + "ethValue", + "timestamp", + "fiatBalance", + "fiatConversion", + "fiatCode" + ], + "type": "object", + "properties": { + "tokenAddress": { + "title": "Token address", + "type": "string", + "minLength": 1 + }, + "token": { + "$ref": "#/definitions/Erc20Info" + }, + "balance": { + "title": "Balance", + "type": "string", + "minLength": 1 + }, + "ethValue": { + "title": "Eth value", + "type": "string", + "minLength": 1 + }, + "timestamp": { + "title": "Timestamp", + "type": "string", + "format": "date-time" + }, + "fiatBalance": { + "title": "Fiat balance", + "type": "string", + "minLength": 1 + }, + "fiatConversion": { + "title": "Fiat conversion", + "type": "string", + "minLength": 1 + }, + "fiatCode": { + "title": "Fiat code", + "type": "string", + "minLength": 1 + } + } + }, + "SafeCreationInfoResponse": { + "required": ["created", "creator", "transactionHash", "factoryAddress", "masterCopy", "setupData"], + "type": "object", + "properties": { + "created": { + "title": "Created", + "type": "string", + "format": "date-time" + }, + "creator": { + "title": "Creator", + "type": "string" + }, + "transactionHash": { + "title": "Transaction hash", + "type": "string" + }, + "factoryAddress": { + "title": "Factory address", + "type": "string" + }, + "masterCopy": { + "title": "Master copy", + "type": "string", + "x-nullable": true + }, + "setupData": { + "title": "Setup data", + "type": "string", + "x-nullable": true + }, + "dataDecoded": { + "title": "Data decoded", + "type": "object", + "readOnly": true + } + } + }, + "SafeDelegateDelete": { + "required": ["safe", "delegate", "signature"], + "type": "object", + "properties": { + "safe": { + "title": "Safe", + "type": "string" + }, + "delegate": { + "title": "Delegate", + "type": "string" + }, + "signature": { + "title": "Signature", + "type": "string" + } + } + }, + "SafeMessage": { + "required": ["message", "signature"], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "object" + }, + "safeAppId": { + "title": "Safe app id", + "type": "integer", + "x-nullable": true + }, + "signature": { + "title": "Signature", + "type": "string" + } + } + }, + "SafeMultisigTransaction": { + "required": [ + "safe", + "to", + "value", + "operation", + "safeTxGas", + "baseGas", + "gasPrice", + "nonce", + "contractTransactionHash", + "sender" + ], + "type": "object", + "properties": { + "safe": { + "title": "Safe", + "type": "string" + }, + "to": { + "title": "To", + "type": "string" + }, + "value": { + "title": "Value", + "type": "integer", + "minimum": 0 + }, + "data": { + "title": "Data", + "type": "string", + "x-nullable": true + }, + "operation": { + "title": "Operation", + "type": "integer", + "minimum": 0 + }, + "gasToken": { + "title": "Gas token", + "type": "string", + "x-nullable": true + }, + "safeTxGas": { + "title": "Safe tx gas", + "type": "integer", + "minimum": 0 + }, + "baseGas": { + "title": "Base gas", + "type": "integer", + "minimum": 0 + }, + "gasPrice": { + "title": "Gas price", + "type": "integer", + "minimum": 0 + }, + "refundReceiver": { + "title": "Refund receiver", + "type": "string", + "x-nullable": true + }, + "nonce": { + "title": "Nonce", + "type": "integer", + "minimum": 0 + }, + "contractTransactionHash": { + "title": "Contract transaction hash", + "type": "string" + }, + "sender": { + "title": "Sender", + "type": "string" + }, + "signature": { + "title": "Signature", + "type": "string", + "x-nullable": true + }, + "origin": { + "title": "Origin", + "type": "string", + "maxLength": 200, + "minLength": 1, + "x-nullable": true + } + } + }, + "SafeMultisigTransactionEstimate": { + "required": ["to", "value", "operation"], + "type": "object", + "properties": { + "to": { + "title": "To", + "type": "string" + }, + "value": { + "title": "Value", + "type": "integer", + "minimum": 0 + }, + "data": { + "title": "Data", + "type": "string", + "x-nullable": true + }, + "operation": { + "title": "Operation", + "type": "integer", + "minimum": 0 + } + } + }, + "SafeMultisigTransactionEstimateResponse": { + "required": ["safeTxGas"], + "type": "object", + "properties": { + "safeTxGas": { + "title": "Safe tx gas", + "type": "string", + "minLength": 1 + } + } + }, + "SafeCollectibleResponse": { + "required": [ + "address", + "tokenName", + "tokenSymbol", + "logoUri", + "id", + "uri", + "name", + "description", + "imageUri", + "metadata" + ], + "type": "object", + "properties": { + "address": { + "title": "Address", + "type": "string", + "minLength": 1 + }, + "tokenName": { + "title": "Token name", + "type": "string", + "minLength": 1 + }, + "tokenSymbol": { + "title": "Token symbol", + "type": "string", + "minLength": 1 + }, + "logoUri": { + "title": "Logo uri", + "type": "string", + "minLength": 1 + }, + "id": { + "title": "Id", + "type": "string", + "minLength": 1 + }, + "uri": { + "title": "Uri", + "type": "string", + "minLength": 1 + }, + "name": { + "title": "Name", + "type": "string", + "minLength": 1 + }, + "description": { + "title": "Description", + "type": "string", + "minLength": 1 + }, + "imageUri": { + "title": "Image uri", + "type": "string", + "minLength": 1 + }, + "metadata": { + "title": "Metadata", + "type": "object", + "additionalProperties": { + "type": "string", + "x-nullable": true + } + } + } + } + } +} diff --git a/apps/dapp/src/safe/open-api/replace-host.sh b/apps/dapp/src/safe/open-api/replace-host.sh new file mode 100755 index 000000000..dd011f283 --- /dev/null +++ b/apps/dapp/src/safe/open-api/replace-host.sh @@ -0,0 +1,6 @@ +#!/bin/bash +if [[ "$VITE_ENV" == "production" ]]; then + sed -ie 's/"host": .*"/"host": '\"safe-transaction-mainnet.safe.global\"'/g' apiV1.json +else + sed -ie 's/"host": .*"/"host": '\"safe-transaction-sepolia.safe.global\"'/g' apiV1.json +fi \ No newline at end of file diff --git a/apps/dapp/src/safe/open-api/use-safe-open-api.tsx b/apps/dapp/src/safe/open-api/use-safe-open-api.tsx new file mode 100644 index 000000000..d7971bdef --- /dev/null +++ b/apps/dapp/src/safe/open-api/use-safe-open-api.tsx @@ -0,0 +1,70 @@ +import { AllTransactionsSchema, SafeMultisigTransactionResponse, V1Service } from './client'; +import { UseQueryResult, useQuery } from '@tanstack/react-query'; + +type SafeApiRes = { + count: number; + next?: string | null; + previous?: string | null; + results: T; +}; + +export const useSafeTxs = ( + safeWalletAddress: string, + walletAddress: string | undefined, + onlyExecuted: boolean, + orderByNonce: boolean, + refetchInterval?: number | false +): UseQueryResult> => + useQuery({ + queryKey: ['getSafeTransactions', safeWalletAddress, walletAddress, onlyExecuted, refetchInterval], + queryFn: () => { + return V1Service.v1SafesMultisigTransactionsList( + safeWalletAddress, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + onlyExecuted ? 'true' : 'false', // should return executed txs, if false only return queued txs + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + orderByNonce ? 'nonce' : undefined, // order asc by nonce, so users see transactions to be executed + ); + }, + refetchInterval, + }); + +export const useSafeAllTransactions = (safeWalletAddress: string): UseQueryResult> => + useQuery({ + queryKey: ['getAllSafeTransactions', safeWalletAddress], + queryFn: () => { + return V1Service.v1SafesAllTransactionsList(safeWalletAddress); + }, + }); + +export const useSafeCheckOwner = ( + safeWalletAddress: string, + ownerAddress: string | undefined +): UseQueryResult => + useQuery({ + queryKey: ['checkSafeOwner', safeWalletAddress, ownerAddress], + queryFn: async () => { + const safeDetails = await V1Service.v1SafesRead(safeWalletAddress); + return safeDetails.owners.filter((o) => o.toLowerCase() === ownerAddress?.toLowerCase()).length > 0; + }, + }); diff --git a/apps/dapp/src/safe/readme.md b/apps/dapp/src/safe/readme.md new file mode 100644 index 000000000..516ec365d --- /dev/null +++ b/apps/dapp/src/safe/readme.md @@ -0,0 +1,43 @@ +# Safe SDK v1.3.0 & Open API + +## sdk folder + +SDK source code facilitates the interaction with the [Safe contracts](https://github.com/safe-global/safe-contracts). + +Majority of the src in this folder was copied from [SafeCore SDK release 33](https://github.com/safe-global/safe-core-sdk/releases/tag/r33). We had to copy it, instead of using the latest [npm package](@safe-global/protocol-kit) for the following reasons: + +- Latest npm version `2.0.0` only allows ethers v6, and current dApp uses ethers v5. In the future when temple dApp migrates to v6, this is the recommended option to migrate to, but meanwhile we need to stick to the [preview version 1.3.0](https://www.npmjs.com/package/@safe-global/protocol-kit/v/1.3.0) which supports ethers v5. +- We tried to use the protocol-kit npm version 1.3.0 as package dependency, but when building the project for production, the app crashes with the following issue: +``` +protocol-kit.js + +Uncaught ReferenceError: Cannot access 'jt' before initialization + at protocol-kit.6526b566.js:1:1206 +``` +- SafeCoreSDK@ProtocolKit src is still needed for sign and execute safe gnosis wallet transactions given the logic of their smart contracts. + +*This is a minimal copy with only the required functions to execute safe contracts v1.3.0 signatures & executions* + +### Source of files copied + +sdk/contracts: + - [config.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/contracts/config.ts) + - [contractInstancesEthers.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/adapters/ethers/contracts/contractInstancesEthers.ts) + - [safeDeploymentContracts.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/contracts/safeDeploymentContracts.ts) + +sdk/signatures: + - [SafeSignature.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/utils/signatures/SafeSignature.ts) + - [utils.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/utils/signatures/utils.ts) + +sdk/transactions: +- [gas.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/utils/transactions/gas.ts) +- [SafeTransaction.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/utils/transactions/SafeTransaction.ts) + +sdk/utils: +- [safeVersions.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/utils/safeVersions.ts) +- [types.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/types/index.ts) +- we've copied various util functions from various files, but main logic/src was copied from [utils.ts](https://github.com/safe-global/safe-core-sdk/blob/r33/packages/protocol-kit/src/Safe.ts) + + +## open-api folder +We didn't copy [SafeCoreSDK@api-kit](https://www.npmjs.com/package/@safe-global/api-kit) src, instead we've used the open api specification from https://safe-transaction-mainnet.safe.global/ and automatically generated the client code to interact with safe rest apis. This gives both more control over the apis we want to use, and also reduces complexity, one less third party dependency to worry. \ No newline at end of file diff --git a/apps/dapp/src/safe/safeContext.tsx b/apps/dapp/src/safe/safeContext.tsx new file mode 100644 index 000000000..fcf530e29 --- /dev/null +++ b/apps/dapp/src/safe/safeContext.tsx @@ -0,0 +1,165 @@ +import { PropsWithChildren, createContext, useContext } from 'react'; +import { useSafeCheckOwner, useSafeTxs } from './open-api/use-safe-open-api'; +import { SafeTableRow } from 'components/Pages/Safe/admin/SafeTxDataTable'; +import { useWallet } from 'providers/WalletProvider'; +import { format } from 'date-fns'; +import { useSafeSdk } from './sdk/use-safe-sdk'; + +export type SafeTransactionCategory = 'queue' | 'history'; +type SafeTransactionCategoryAction = 'return' | 'add' | 'clear'; +export type SafeStatus = 'unknown' | 'awaiting_signing' | 'awaiting_execution' | 'loading' | 'successful' | 'error'; +interface ISafeTransactionsContext { + safeAddress: string; + isLoading: () => boolean; + tableRows: ( + safeTxCategory: SafeTransactionCategory, + updateSafeTableRow: (safeTxHash: string, newValue?: SafeTableRow) => void + ) => Promise; +} +const SafeTransactionsContext = createContext(undefined); + +type SafeTransactionsContextProviderProps = { + safeAddress: string; +}; +export function SafeTransactionsContextProvider({ + children, + safeAddress, +}: PropsWithChildren) { + const safeQueuedTableRows: SafeTableRow[] = []; + const safeHistoryTableRows: SafeTableRow[] = []; + const { walletAddress, signer } = useWallet(); + const { data: isSafeOwner } = useSafeCheckOwner(safeAddress, walletAddress); + const { signSafeTx, executeSafeTx } = useSafeSdk(signer, safeAddress); + + const safeQueuedTransactions = useSafeTxs(safeAddress, walletAddress, false, true, 5000); + const safeExecutedTransactions = useSafeTxs(safeAddress, walletAddress, true, false, 5000); + + const getQueuedTransactions = (safeTxCategory: SafeTransactionCategory) => { + if (safeTxCategory === 'queue') return safeQueuedTransactions.data?.results ?? []; + if (safeTxCategory === 'history') return safeExecutedTransactions.data?.results ?? []; + }; + + const getprevSafeTableRow = (safeTxCategory: SafeTransactionCategory, safeTransactionHash: string) => { + switch (safeTxCategory) { + case 'queue': + return safeQueuedTableRows.find((str) => str.safeTxHash === safeTransactionHash); + case 'history': + return safeHistoryTableRows.find((str) => str.safeTxHash === safeTransactionHash); + } + }; + + const isLoading = () => { + return safeQueuedTransactions.isLoading || safeExecutedTransactions.isLoading; + }; + + const tableRows = async ( + safeTxCategory: SafeTransactionCategory, + updateSafeTableRow: (safeTxHash: string, newValue?: SafeTableRow) => void + ) => { + safeTxCategoryAction('clear', safeTxCategory); + await getQueuedTransactions(safeTxCategory)?.map(async (tx) => { + const txConfirmations = tx.confirmations ?? []; + const thresholdReached = txConfirmations.length >= tx.confirmationsRequired; + const alreadySigned = + txConfirmations.filter((conf) => conf.owner.toLowerCase() === walletAddress?.toLowerCase()).length > 0; + const isOwner = isSafeOwner ?? false; + let status: SafeStatus = thresholdReached ? 'awaiting_execution' : 'awaiting_signing'; + if (tx.isSuccessful && tx.isExecuted) { + status = 'successful'; + } else if (!tx.isSuccessful && tx.isExecuted) { + status = 'error'; + } + let rowButtonLabel = 'N/A'; + let rowButtonDisabled = true; + switch (status) { + case 'awaiting_signing': + rowButtonLabel = 'SIGN'; + rowButtonDisabled = !walletAddress || alreadySigned || !isOwner; + break; + case 'awaiting_execution': + rowButtonLabel = 'EXECUTE'; + rowButtonDisabled = !walletAddress && !isOwner; + break; + } + + const tmpSafeRow: SafeTableRow = { + date: format(new Date(tx.submissionDate), 'yyyy-MM-dd H:mm'), + txHash: tx.transactionHash, + safeTxHash: tx.safeTxHash, + status, + button: { + label: rowButtonLabel, + disabled: rowButtonDisabled, + }, + confirmations: `${txConfirmations.length}/${tx.confirmationsRequired}`, + alreadySigned, + type: tx.dataDecoded?.method ?? (tx.value.length > 1 ? 'transfer' : undefined), + isOwner, + nonce: tx.nonce, + isExpanded: false, + dataRaw: tx.data, + dataDecode: JSON.stringify(tx.dataDecoded, null, 2), + action: async () => { + const prevSafeTableRow = getprevSafeTableRow(safeTxCategory, tx.safeTxHash); + try { + if (!prevSafeTableRow) throw 'prevSafeTableRow undefined'; + switch (status) { + case 'awaiting_signing': + await signSafeTx(tx.safeTxHash); + updateSafeTableRow(prevSafeTableRow.safeTxHash, { ...prevSafeTableRow, status: 'loading' }); + return; + case 'awaiting_execution': + await executeSafeTx(tx.safeTxHash); + updateSafeTableRow(prevSafeTableRow.safeTxHash, { ...prevSafeTableRow, status: 'loading' }); + return; + } + } catch (e) { + if (!prevSafeTableRow) throw 'prevSafeTableRow undefined'; + updateSafeTableRow(prevSafeTableRow.safeTxHash, { ...prevSafeTableRow, status: 'error' }); + } + }, + }; + return safeTxCategoryAction('add', safeTxCategory, tmpSafeRow); + }); + return safeTxCategoryAction('return', safeTxCategory) ?? []; + }; + + const safeTxCategoryAction = ( + safeTxCategoryAction: SafeTransactionCategoryAction, + safeTxCategory: SafeTransactionCategory, + selectedSafeRow?: SafeTableRow + ) => { + switch (safeTxCategoryAction) { + case 'return': + if (safeTxCategory === 'queue') return safeQueuedTableRows; + if (safeTxCategory === 'history') return safeHistoryTableRows; + break; + case 'add': + if (safeTxCategory === 'queue') selectedSafeRow && safeQueuedTableRows.push(selectedSafeRow); + if (safeTxCategory === 'history') selectedSafeRow && safeHistoryTableRows.push(selectedSafeRow); + break; + case 'clear': + if (safeTxCategory === 'queue') safeQueuedTableRows.splice(0, safeQueuedTableRows.length); + if (safeTxCategory === 'history') safeHistoryTableRows.splice(0, safeHistoryTableRows.length); + break; + } + }; + + const context: ISafeTransactionsContext = { + safeAddress, + tableRows, + isLoading, + }; + + return {children}; +} + +export const useSafeTransactions = () => { + const context = useContext(SafeTransactionsContext); + + if (context === undefined) { + throw new Error('useSafeTransactions must be used within SafeTransactionsContext'); + } + + return context; +}; diff --git a/apps/dapp/src/safe/sdk/contracts/config.ts b/apps/dapp/src/safe/sdk/contracts/config.ts new file mode 100644 index 000000000..3f7058210 --- /dev/null +++ b/apps/dapp/src/safe/sdk/contracts/config.ts @@ -0,0 +1,33 @@ +import { SafeVersion } from '@safe-global/safe-core-sdk-types'; + +export const DEFAULT_SAFE_VERSION: SafeVersion = '1.3.0'; + +type SafeDeploymentsVersions = { + [version: string]: { + safeMasterCopyVersion: string; + safeMasterCopyL2Version?: string; + safeProxyFactoryVersion: string; + compatibilityFallbackHandler: string; + multiSendVersion: string; + multiSendCallOnlyVersion?: string; + signMessageLibVersion?: string; + createCallVersion?: string; + }; +}; + +export const safeDeploymentsVersions: SafeDeploymentsVersions = { + '1.3.0': { + safeMasterCopyVersion: '1.3.0', + safeMasterCopyL2Version: '1.3.0', + safeProxyFactoryVersion: '1.3.0', + compatibilityFallbackHandler: '1.3.0', + multiSendVersion: '1.3.0', + multiSendCallOnlyVersion: '1.3.0', + signMessageLibVersion: '1.3.0', + createCallVersion: '1.3.0', + }, +}; + +export const safeDeploymentsL1ChainIds = [ + 1, // Ethereum Mainnet +]; diff --git a/apps/dapp/src/safe/sdk/contracts/contractInstancesEthers.ts b/apps/dapp/src/safe/sdk/contracts/contractInstancesEthers.ts new file mode 100644 index 000000000..ad8c829f0 --- /dev/null +++ b/apps/dapp/src/safe/sdk/contracts/contractInstancesEthers.ts @@ -0,0 +1,22 @@ +import { Signer } from '@ethersproject/abstract-signer'; +import { Gnosis_safe__factory as SafeMasterCopy_V1_3_0 } from 'types/typechain/factories/@safe-global/safe-deployments/v1.3.0/Gnosis_safe__factory'; +import { Multi_send__factory as MultiSend_V1_3_0 } from 'types/typechain/factories/@safe-global/safe-deployments/v1.3.0/Multi_send__factory'; +import { Multi_send_call_only__factory as MultiSendCallOnly_V1_3_0 } from 'types/typechain/factories/@safe-global/safe-deployments/v1.3.0/Multi_send_call_only__factory'; +import { Simulate_tx_accessor__factory as SimulateTxAccessor_V1_3_0 } from 'types/typechain/factories/@safe-global/safe-deployments/v1.3.0/Simulate_tx_accessor__factory'; +import { Gnosis_safe as Safe_V1_3_0 } from 'types/typechain/@safe-global/safe-deployments/v1.3.0/Gnosis_safe'; + +export function getSafeContractInstance(contractAddress: string, signer: Signer): Safe_V1_3_0 { + return SafeMasterCopy_V1_3_0.connect(contractAddress, signer); +} + +export function getMultiSendContractInstance(contractAddress: string, signer: Signer) { + return MultiSend_V1_3_0.connect(contractAddress, signer); +} + +export function getMultiSendCallOnlyContractInstance(contractAddress: string, signer: Signer) { + return MultiSendCallOnly_V1_3_0.connect(contractAddress, signer); +} + +export function getSimulateTxAccessorContractInstance(contractAddress: string, signer: Signer) { + return SimulateTxAccessor_V1_3_0.connect(contractAddress, signer); +} diff --git a/apps/dapp/src/safe/sdk/contracts/safeDeploymentContracts.ts b/apps/dapp/src/safe/sdk/contracts/safeDeploymentContracts.ts new file mode 100644 index 000000000..fdb5d3295 --- /dev/null +++ b/apps/dapp/src/safe/sdk/contracts/safeDeploymentContracts.ts @@ -0,0 +1,170 @@ +import { Signer } from '@ethersproject/abstract-signer'; +import { SafeVersion } from '@safe-global/safe-core-sdk-types'; +import { + DeploymentFilter, + SingletonDeployment, + getMultiSendCallOnlyDeployment, + getMultiSendDeployment, + getSafeL2SingletonDeployment, + getSafeSingletonDeployment, + getSimulateTxAccessorDeployment, +} from '@safe-global/safe-deployments'; +import { safeDeploymentsL1ChainIds, safeDeploymentsVersions } from './config'; +import { ContractNetworkConfig } from '../utils/types'; +import { + getMultiSendCallOnlyContractInstance, + getMultiSendContractInstance, + getSafeContractInstance, + getSimulateTxAccessorContractInstance, +} from './contractInstancesEthers'; +import { Gnosis_safe as SafeMasterCopy_V1_3_0 } from 'types/typechain/@safe-global/safe-deployments/v1.3.0/Gnosis_safe'; +import { Multi_send as MultiSend_V1_3_0 } from 'types/typechain/@safe-global/safe-deployments/v1.3.0/Multi_send'; +import { Multi_send_call_only as MultiSendCallOnly_V1_3_0 } from 'types/typechain/@safe-global/safe-deployments/v1.3.0/Multi_send_call_only'; +import { Simulate_tx_accessor as SimulateTxAccessor_V1_3_0 } from 'types/typechain/@safe-global/safe-deployments/v1.3.0/Simulate_tx_accessor'; + +interface GetContractInstanceProps { + signer: Signer; + safeVersion: SafeVersion; + customContracts?: ContractNetworkConfig; +} + +interface GetSafeContractInstanceProps extends GetContractInstanceProps { + isL1SafeMasterCopy?: boolean; + customSafeAddress?: string; +} + +export function getSafeContractDeploymentDetails( + safeVersion: SafeVersion, + chainId: number, + isL1SafeMasterCopy = false +): SingletonDeployment { + const version = safeDeploymentsVersions[safeVersion].safeMasterCopyVersion; + const filters: DeploymentFilter = { version, network: chainId.toString(), released: true }; + if (safeDeploymentsL1ChainIds.includes(chainId) || isL1SafeMasterCopy) { + const safeSingletonContractDetails = getSafeSingletonDeployment(filters); + console.debug('using SafeContract L1', safeSingletonContractDetails); + if (!safeSingletonContractDetails) throw Error('undefined safeSingletonContractDetails'); + return safeSingletonContractDetails; + } + const safeL2SingletonContractDetails = getSafeL2SingletonDeployment(filters); + console.debug('using SafeContract L2', safeL2SingletonContractDetails); + if (!safeL2SingletonContractDetails) throw Error('undefined safeL2SingletonContractDetails'); + return safeL2SingletonContractDetails; +} + +export function getMultiSendCallOnlyContractDeploymentDetails( + safeVersion: SafeVersion, + chainId: number +): SingletonDeployment { + const version = safeDeploymentsVersions[safeVersion].multiSendCallOnlyVersion; + const multiSendCallOnlyContractDeploymentDetails = getMultiSendCallOnlyDeployment({ + version, + network: chainId.toString(), + released: true, + }); + if (!multiSendCallOnlyContractDeploymentDetails) throw Error('undefined multiSendCallOnlyContractDeploymentDetails'); + return multiSendCallOnlyContractDeploymentDetails; +} + +export function getMultiSendContractDeploymentDetails(safeVersion: SafeVersion, chainId: number): SingletonDeployment { + const version = safeDeploymentsVersions[safeVersion].multiSendVersion; + const multiSendContractDeploymentDetails = getMultiSendDeployment({ + version, + network: chainId.toString(), + released: true, + }); + if (!multiSendContractDeploymentDetails) throw Error('multiSendContractDeploymentDetails undefined'); + return multiSendContractDeploymentDetails; +} + +export function getSimulateTxAccessorContractDeploymentDetails( + safeVersion: SafeVersion, + chainId: number +): SingletonDeployment { + const version = safeDeploymentsVersions[safeVersion].createCallVersion; + const simulateTxAccessorDeploymentDetails = getSimulateTxAccessorDeployment({ + version, + network: chainId.toString(), + released: true, + }); + if (!simulateTxAccessorDeploymentDetails) throw Error('undefined simulateTxAccessorDeploymentDetails'); + return simulateTxAccessorDeploymentDetails; +} + +export async function getSafeContract({ + signer, + safeVersion, + customSafeAddress, + customContracts, +}: GetSafeContractInstanceProps): Promise { + const safeContractDeploymentDetails = getSafeContractDeploymentDetails(safeVersion, await signer.getChainId()); + const safeContract = getSafeContractInstance( + customSafeAddress ?? customContracts?.safeMasterCopyAddress ?? safeContractDeploymentDetails.defaultAddress, + signer + ); + const isContractDeployed = (await signer.provider?.getCode(safeContract.address)) !== '0x'; + if (!isContractDeployed) { + throw new Error('SafeProxy contract is not deployed on the current network'); + } + return safeContract; +} + +export async function getMultiSendContract({ + signer, + safeVersion, + customContracts, +}: GetContractInstanceProps): Promise { + const multiSendContractDeploymentDetails = getMultiSendContractDeploymentDetails( + safeVersion, + await signer.getChainId() + ); + const multiSendContract = getMultiSendContractInstance( + customContracts?.safeMasterCopyAddress ?? multiSendContractDeploymentDetails.defaultAddress, + signer + ); + const isContractDeployed = await signer.provider?.getCode(multiSendContract.address); + if (!isContractDeployed) { + throw new Error('MultiSend contract is not deployed on the current network'); + } + return multiSendContract; +} + +export async function getMultiSendCallOnlyContract({ + signer, + safeVersion, + customContracts, +}: GetContractInstanceProps): Promise { + const multiSendCallOnlyContractDeploymentDetails = getMultiSendCallOnlyContractDeploymentDetails( + safeVersion, + await signer.getChainId() + ); + const multiSendCallOnlyContract = getMultiSendCallOnlyContractInstance( + customContracts?.safeMasterCopyAddress ?? multiSendCallOnlyContractDeploymentDetails.defaultAddress, + signer + ); + const isContractDeployed = await signer.provider?.getCode(multiSendCallOnlyContract.address); + if (!isContractDeployed) { + throw new Error('MultiSendCallOnly contract is not deployed on the current network'); + } + return multiSendCallOnlyContract; +} + +export async function getSimulateTxAccessorContract({ + signer, + safeVersion, + customContracts, +}: GetContractInstanceProps): Promise { + const simulateTxAccessorContractDeploymentDetails = getSimulateTxAccessorContractDeploymentDetails( + safeVersion, + await signer.getChainId() + ); + const simulateTxAccessorContract = getSimulateTxAccessorContractInstance( + customContracts?.safeMasterCopyAddress ?? simulateTxAccessorContractDeploymentDetails.defaultAddress, + signer + ); + const isContractDeployed = await signer.provider?.getCode(simulateTxAccessorContract.address); + if (!isContractDeployed) { + throw new Error('SimulateTxAccessor contract is not deployed on the current network'); + } + return simulateTxAccessorContract; +} diff --git a/apps/dapp/src/safe/sdk/signatures/SafeSignature.ts b/apps/dapp/src/safe/sdk/signatures/SafeSignature.ts new file mode 100644 index 000000000..406d97386 --- /dev/null +++ b/apps/dapp/src/safe/sdk/signatures/SafeSignature.ts @@ -0,0 +1,36 @@ +import { SafeSignature } from '@safe-global/safe-core-sdk-types'; + +export class EthSafeSignature implements SafeSignature { + signer: string; + data: string; + + /** + * Creates an instance of a Safe signature. + * + * @param signer - Ethers signer + * @param signature - The Safe signature + * @returns The Safe signature instance + */ + constructor(signer: string, signature: string) { + this.signer = signer; + this.data = signature; + } + + /** + * Returns the static part of the Safe signature. + * + * @returns The static part of the Safe signature + */ + staticPart(/* dynamicOffset: number */) { + return this.data; + } + + /** + * Returns the dynamic part of the Safe signature. + * + * @returns The dynamic part of the Safe signature + */ + dynamicPart() { + return ''; + } +} diff --git a/apps/dapp/src/safe/sdk/signatures/utils.ts b/apps/dapp/src/safe/sdk/signatures/utils.ts new file mode 100644 index 000000000..a8a364d84 --- /dev/null +++ b/apps/dapp/src/safe/sdk/signatures/utils.ts @@ -0,0 +1,83 @@ +import { SafeSignature } from '@safe-global/safe-core-sdk-types'; +import { bufferToHex, ecrecover, pubToAddress } from 'ethereumjs-util'; +import { EthSafeSignature } from './SafeSignature'; +import { sameString } from '../utils/utils'; + +export function generatePreValidatedSignature(ownerAddress: string): SafeSignature { + const signature = + '0x000000000000000000000000' + + ownerAddress.slice(2) + + '0000000000000000000000000000000000000000000000000000000000000000' + + '01'; + + return new EthSafeSignature(ownerAddress, signature); +} + +export function isTxHashSignedWithPrefix(txHash: string, signature: string, ownerAddress: string): boolean { + let hasPrefix; + try { + const rsvSig = { + r: Buffer.from(signature.slice(2, 66), 'hex'), + s: Buffer.from(signature.slice(66, 130), 'hex'), + v: parseInt(signature.slice(130, 132), 16), + }; + const recoveredData = ecrecover(Buffer.from(txHash.slice(2), 'hex'), rsvSig.v, rsvSig.r, rsvSig.s); + const recoveredAddress = bufferToHex(pubToAddress(recoveredData)); + hasPrefix = !sameString(recoveredAddress, ownerAddress); + } catch (e) { + hasPrefix = true; + } + return hasPrefix; +} + +type AdjustVOverload = { + (signingMethod: 'eth_signTypedData', signature: string): string; + (signingMethod: 'eth_sign', signature: string, safeTxHash: string, sender: string): string; +}; + +export const adjustVInSignature: AdjustVOverload = ( + signingMethod: 'eth_sign' | 'eth_signTypedData', + signature: string, + safeTxHash?: string, + signerAddress?: string +): string => { + const ETHEREUM_V_VALUES = [0, 1, 27, 28]; + const MIN_VALID_V_VALUE_FOR_SAFE_ECDSA = 27; + let signatureV = parseInt(signature.slice(-2), 16); + if (!ETHEREUM_V_VALUES.includes(signatureV)) { + throw new Error('Invalid signature'); + } + if (signingMethod === 'eth_sign') { + /* + The Safe's expected V value for ECDSA signature is: + - 27 or 28 + - 31 or 32 if the message was signed with a EIP-191 prefix. Should be calculated as ECDSA V value + 4 + Some wallets do that, some wallets don't, V > 30 is used by contracts to differentiate between + prefixed and non-prefixed messages. The only way to know if the message was signed with a + prefix is to check if the signer address is the same as the recovered address. + + More info: + https://docs.safe.global/safe-core-protocol/signatures + */ + if (signatureV < MIN_VALID_V_VALUE_FOR_SAFE_ECDSA) { + signatureV += MIN_VALID_V_VALUE_FOR_SAFE_ECDSA; + } + const adjustedSignature = signature.slice(0, -2) + signatureV.toString(16); + const signatureHasPrefix = isTxHashSignedWithPrefix( + safeTxHash as string, + adjustedSignature, + signerAddress as string + ); + if (signatureHasPrefix) { + signatureV += 4; + } + } + if (signingMethod === 'eth_signTypedData') { + // Metamask with ledger returns V=0/1 here too, we need to adjust it to be ethereum's valid value (27 or 28) + if (signatureV < MIN_VALID_V_VALUE_FOR_SAFE_ECDSA) { + signatureV += MIN_VALID_V_VALUE_FOR_SAFE_ECDSA; + } + } + signature = signature.slice(0, -2) + signatureV.toString(16); + return signature; +}; diff --git a/apps/dapp/src/safe/sdk/transactions/SafeTransaction.ts b/apps/dapp/src/safe/sdk/transactions/SafeTransaction.ts new file mode 100644 index 000000000..54bc72e5e --- /dev/null +++ b/apps/dapp/src/safe/sdk/transactions/SafeTransaction.ts @@ -0,0 +1,28 @@ +import { SafeSignature, SafeTransaction, SafeTransactionData } from '@safe-global/safe-core-sdk-types'; + +class EthSafeTransaction implements SafeTransaction { + data: SafeTransactionData; + signatures: Map = new Map(); + + constructor(data: SafeTransactionData) { + this.data = data; + } + + addSignature(signature: SafeSignature): void { + this.signatures.set(signature.signer.toLowerCase(), signature); + } + + encodedSignatures(): string { + const signers = Array.from(this.signatures.keys()).sort(); + let staticParts = ''; + let dynamicParts = ''; + signers.forEach((signerAddress) => { + const signature = this.signatures.get(signerAddress); + staticParts += signature?.staticPart(/*baseOffset + dynamicParts.length / 2*/).slice(2); + dynamicParts += signature?.dynamicPart(); + }); + return '0x' + staticParts + dynamicParts; + } +} + +export default EthSafeTransaction; diff --git a/apps/dapp/src/safe/sdk/transactions/gas.ts b/apps/dapp/src/safe/sdk/transactions/gas.ts new file mode 100644 index 000000000..a6b85f1e8 --- /dev/null +++ b/apps/dapp/src/safe/sdk/transactions/gas.ts @@ -0,0 +1,64 @@ +import { Signer } from '@ethersproject/abstract-signer'; +import { OperationType, SafeVersion } from '@safe-global/safe-core-sdk-types'; +import { Gnosis_safe as Safe_V1_3_0 } from 'types/typechain/@safe-global/safe-deployments/v1.3.0/Gnosis_safe'; +import { getSimulateTxAccessorContract } from '../contracts/safeDeploymentContracts'; + +export async function estimateGas( + safeVersion: SafeVersion, + safeContract: Safe_V1_3_0, + signer: Signer, + to: string, + valueInWei: string, + data: string, + operation: OperationType +) { + const simulateTxAccessorContract = await getSimulateTxAccessorContract({ signer, safeVersion }); + const transactionDataToEstimate = simulateTxAccessorContract.interface.encodeFunctionData('simulate', [ + to, + valueInWei, + data, + operation, + ]); + const safeFunctionToEstimate = safeContract.interface.encodeFunctionData('simulateAndRevert', [ + await simulateTxAccessorContract.address, + transactionDataToEstimate, + ]); + const safeAddress = safeContract.address; + const transactionToEstimateGas = { + to: safeAddress, + value: '0', + data: safeFunctionToEstimate, + from: safeAddress, + }; + + try { + const encodedResponse = await signer.call(transactionToEstimateGas); + + return Number('0x' + encodedResponse.slice(184).slice(0, 10)).toString(); + } catch (error: any) { + return parseSafeTxGasErrorResponse(error); + } +} + +function decodeSafeTxGas(encodedSafeTxGas: string): string { + return Number('0x' + encodedSafeTxGas.slice(184).slice(0, 10)).toString(); +} + +function parseSafeTxGasErrorResponse(error: any) { + // Ethers + if (error?.error?.body) { + const revertData = JSON.parse(error.error.body).error.data; + if (revertData && revertData.startsWith('Reverted ')) { + const [, encodedResponse] = revertData.split('Reverted '); + const safeTxGas = decodeSafeTxGas(encodedResponse); + + return safeTxGas; + } + } + + // Web3 + const [, encodedResponse] = error.message.split('return data: '); + const safeTxGas = decodeSafeTxGas(encodedResponse); + + return safeTxGas; +} diff --git a/apps/dapp/src/safe/sdk/use-safe-sdk.tsx b/apps/dapp/src/safe/sdk/use-safe-sdk.tsx new file mode 100644 index 000000000..79d4c5abe --- /dev/null +++ b/apps/dapp/src/safe/sdk/use-safe-sdk.tsx @@ -0,0 +1,134 @@ +import { Gnosis_safe as SafeMasterCopy_V1_3_0 } from 'types/typechain/@safe-global/safe-deployments/v1.3.0/Gnosis_safe'; +import { BigNumber, Signer, ethers } from 'ethers'; +import { + copyTransaction, + getEncodedTransaction, + getOwners, + getOwnersWhoApprovedTx, + getThreshold, + getTransactionHash, + isSafeMultisigTransactionResponse, + toSafeTransactionType, +} from './utils/utils'; +import { V1Service, SafeMultisigConfirmation } from 'safe/open-api/client'; +import { Nullable } from 'types/util'; +import { + SafeMultisigTransactionResponse, + TransactionOptions, + TransactionResult, +} from '@safe-global/safe-core-sdk-types'; +import { adjustVInSignature, generatePreValidatedSignature } from './signatures/utils'; +import { getSafeContract } from './contracts/safeDeploymentContracts'; +import { DEFAULT_SAFE_VERSION } from './contracts/config'; + + +export const useSafeSdk = (signer: Nullable, safeAddress: string) => { + + const signSafeTx = async (safeTxHash: string) => { + if (!signer) { + console.error('signer undefined'); + return; + } + const signerAddress = await signer.getAddress(); + const messageArray = ethers.utils.arrayify(safeTxHash); + + let tmpSignature = await signer.signMessage(messageArray); + tmpSignature = adjustVInSignature('eth_sign', tmpSignature, safeTxHash, signerAddress); + const safeSignature: SafeMultisigConfirmation = { + signature: tmpSignature, + }; + await V1Service.v1MultisigTransactionsConfirmationsCreate(safeTxHash, safeSignature); + }; + + const executeSafeTx = async ( + safeTxHash: string, + options?: TransactionOptions + ): Promise => { + if (!signer) { + throw new Error('signer undefined'); + } + const txTmp = await V1Service.v1MultisigTransactionsRead(safeTxHash); + const safeTransaction: SafeMultisigTransactionResponse = { + ...txTmp, + data: txTmp.data ?? undefined, + gasToken: txTmp.gasToken!, + refundReceiver: txTmp.refundReceiver ?? undefined, + fee: txTmp.fee?.toString(), + origin: txTmp.origin!, + signatures: txTmp.signatures ?? undefined, + }; + const safeContract = (await getSafeContract({ + signer, + safeVersion: DEFAULT_SAFE_VERSION, + customSafeAddress: safeAddress, + })) as SafeMasterCopy_V1_3_0; + + const transaction = isSafeMultisigTransactionResponse(safeTransaction) + ? await toSafeTransactionType(safeContract, signer, safeTransaction) + : safeTransaction; + + const signedSafeTransaction = await copyTransaction(safeContract, signer, transaction); + const txHash = await getTransactionHash(safeContract, signedSafeTransaction); + const ownersWhoApprovedTx = await getOwnersWhoApprovedTx(safeContract, txHash); + for (const owner of ownersWhoApprovedTx) { + signedSafeTransaction.addSignature(generatePreValidatedSignature(owner)); + } + const owners = await getOwners(safeContract); + const threshold = await getThreshold(safeContract); + const signerAddress = await signer.getAddress(); + if (threshold > signedSafeTransaction.signatures.size && signerAddress && owners.includes(signerAddress)) { + signedSafeTransaction.addSignature(generatePreValidatedSignature(signerAddress)); + } + + if (threshold > signedSafeTransaction.signatures.size) { + const signaturesMissing = threshold - signedSafeTransaction.signatures.size; + throw new Error( + `There ${signaturesMissing > 1 ? 'are' : 'is'} ${signaturesMissing} signature${ + signaturesMissing > 1 ? 's' : '' + } missing` + ); + } + + const value = BigNumber.from(signedSafeTransaction.data.value); + if (!value.isZero()) { + const balance = await signer.getBalance(); + if (value.gt(BigNumber.from(balance))) { + throw new Error('Not enough Ether funds'); + } + } + + if (options?.gas && options?.gasLimit) { + throw new Error('Cannot specify gas and gasLimit together in transaction options'); + } + const sst = signedSafeTransaction.data; + try { + // Use this encoded data to test on tenderly for a simulated tx e.g. https://dashboard.tenderly.co/public/safe/safe-apps/simulator/8aa753dc-43fa-4cf6-b37b-f0da7b499f18 + const encodedTx = await getEncodedTransaction(safeContract, signedSafeTransaction); + console.debug('encodedTx', encodedTx); + const txResponse = await safeContract.execTransaction( + sst.to, + sst.value, + sst.data, + sst.operation, + sst.safeTxGas, + sst.baseGas, + sst.gasPrice, + sst.gasToken, + sst.refundReceiver, + signedSafeTransaction.encodedSignatures(), + { + from: signerAddress, + ...options, + } + ); + return txResponse; + } catch (e) { + throw e; + } + }; + + return { + signSafeTx, + executeSafeTx + } +} diff --git a/apps/dapp/src/safe/sdk/utils/safeVersions.ts b/apps/dapp/src/safe/sdk/utils/safeVersions.ts new file mode 100644 index 000000000..89592a360 --- /dev/null +++ b/apps/dapp/src/safe/sdk/utils/safeVersions.ts @@ -0,0 +1,25 @@ +import semver from 'semver' + +export enum SAFE_FEATURES { + SAFE_TX_GAS_OPTIONAL = 'SAFE_TX_GAS_OPTIONAL', + SAFE_TX_GUARDS = 'SAFE_TX_GUARDS', + SAFE_FALLBACK_HANDLER = 'SAFE_FALLBACK_HANDLER', + ETH_SIGN = 'ETH_SIGN', + ACCOUNT_ABSTRACTION = 'ACCOUNT_ABSTRACTION' +} + +const SAFE_FEATURES_BY_VERSION: Record = { + [SAFE_FEATURES.SAFE_TX_GAS_OPTIONAL]: '>=1.3.0', + [SAFE_FEATURES.SAFE_TX_GUARDS]: '>=1.3.0', + [SAFE_FEATURES.SAFE_FALLBACK_HANDLER]: '>=1.1.1', + [SAFE_FEATURES.ETH_SIGN]: '>=1.1.0', + [SAFE_FEATURES.ACCOUNT_ABSTRACTION]: '>=1.3.0' +} + +export const hasSafeFeature = (feature: SAFE_FEATURES, version: string): boolean => { + if (!(feature in SAFE_FEATURES_BY_VERSION)) { + return false + } + + return semver.satisfies(version, SAFE_FEATURES_BY_VERSION[feature]) +} diff --git a/apps/dapp/src/safe/sdk/utils/types.ts b/apps/dapp/src/safe/sdk/utils/types.ts new file mode 100644 index 000000000..37f96c3a1 --- /dev/null +++ b/apps/dapp/src/safe/sdk/utils/types.ts @@ -0,0 +1,174 @@ +import { Signer } from '@ethersproject/abstract-signer' +import { + EthAdapter, + MetaTransactionData, + SafeTransactionDataPartial, + SafeVersion +} from '@safe-global/safe-core-sdk-types' +import { AbiItem } from 'web3-utils' +import { Gnosis_safe as Safe_V1_3_0 } from 'types/typechain/@safe-global/safe-deployments/v1.3.0/Gnosis_safe' + +export type SafeTransactionOptionalProps = Pick< + SafeTransactionDataPartial, + 'safeTxGas' | 'baseGas' | 'gasPrice' | 'gasToken' | 'refundReceiver' | 'nonce' +> + +export interface SafeAccountConfig { + owners: string[] + threshold: number + to?: string + data?: string + fallbackHandler?: string + paymentToken?: string + payment?: number + paymentReceiver?: string +} + +export interface SafeDeploymentConfig { + saltNonce?: string + safeVersion?: SafeVersion +} + +export interface PredictedSafeProps { + safeAccountConfig: SafeAccountConfig + safeDeploymentConfig?: SafeDeploymentConfig +} + +export interface ContractNetworkConfig { + /** safeMasterCopyAddress - Address of the Safe Master Copy contract deployed on a specific network */ + safeMasterCopyAddress: string + /** safeMasterCopyAbi - Abi of the Safe Master Copy contract deployed on a specific network */ + safeMasterCopyAbi?: AbiItem | AbiItem[] + /** safeProxyFactoryAddress - Address of the SafeProxyFactory contract deployed on a specific network */ + safeProxyFactoryAddress: string + /** safeProxyFactoryAbi - Abi of the SafeProxyFactory contract deployed on a specific network */ + safeProxyFactoryAbi?: AbiItem | AbiItem[] + /** multiSendAddress - Address of the MultiSend contract deployed on a specific network */ + multiSendAddress: string + /** multiSendAbi - Abi of the MultiSend contract deployed on a specific network */ + multiSendAbi?: AbiItem | AbiItem[] + /** multiSendCallOnlyAddress - Address of the MultiSendCallOnly contract deployed on a specific network */ + multiSendCallOnlyAddress: string + /** multiSendCallOnlyAbi - Abi of the MultiSendCallOnly contract deployed on a specific network */ + multiSendCallOnlyAbi?: AbiItem | AbiItem[] + /** fallbackHandlerAddress - Address of the Fallback Handler contract deployed on a specific network */ + fallbackHandlerAddress: string + /** fallbackHandlerAbi - Abi of the Fallback Handler contract deployed on a specific network */ + fallbackHandlerAbi?: AbiItem | AbiItem[] + /** signMessageLibAddress - Address of the SignMessageLib contract deployed on a specific network */ + signMessageLibAddress: string + /** signMessageLibAbi - Abi of the SignMessageLib contract deployed on a specific network */ + signMessageLibAbi?: AbiItem | AbiItem[] + /** createCallAddress - Address of the CreateCall contract deployed on a specific network */ + createCallAddress: string + /** createCallAbi - Abi of the CreateCall contract deployed on a specific network */ + createCallAbi?: AbiItem | AbiItem[] + /** simulateTxAccessorAddress - Address of the SimulateTxAccessor contract deployed on a specific network */ + simulateTxAccessorAddress: string + /** simulateTxAccessorAbi - Abi of the SimulateTxAccessor contract deployed on a specific network */ + simulateTxAccessorAbi?: AbiItem | AbiItem[] +} + +export interface ContractNetworksConfig { + /** id - Network id */ + [id: string]: ContractNetworkConfig +} + +type SafeConfigWithSafeAddressProps = { + /** safeAddress - The address of the Safe account to use */ + safeAddress: string + /** predictedSafe - The configuration of the Safe that is not yet deployed */ + predictedSafe?: never +} + +export type SafeConfigProps = { + /** ethAdapter - Ethereum adapter */ + ethAdapter: EthAdapter + /** isL1SafeMasterCopy - Forces to use the Safe L1 version of the contract instead of the L2 version */ + isL1SafeMasterCopy?: boolean + /** contractNetworks - Contract network configuration */ + contractNetworks?: ContractNetworksConfig +} + +export type SafeConfigWithSafeAddress = SafeConfigProps & SafeConfigWithSafeAddressProps + +type ConnectSafeConfigWithSafeAddressProps = { + /** safeAddress - The address of the Safe account to use */ + safeAddress?: string + /** predictedSafe - The configuration of the Safe that is not yet deployed */ + predictedSafe?: never +} + +type ConnectSafeConfigWithPredictedSafeProps = { + /** safeAddress - The address of the Safe account to use */ + safeAddress?: never + /** predictedSafe - The configuration of the Safe that is not yet deployed */ + predictedSafe?: PredictedSafeProps +} + +type ConnectSafeConfigProps = { + /** ethAdapter - Ethereum adapter */ + ethAdapter?: EthAdapter + /** isL1SafeMasterCopy - Forces to use the Safe L1 version of the contract instead of the L2 version */ + isL1SafeMasterCopy?: boolean + /** contractNetworks - Contract network configuration */ + contractNetworks?: ContractNetworksConfig +} + +export type ConnectSafeConfigWithSafeAddress = ConnectSafeConfigProps & + ConnectSafeConfigWithSafeAddressProps +export type ConnectSafeConfigWithPredictedSafe = ConnectSafeConfigProps & + ConnectSafeConfigWithPredictedSafeProps +export type ConnectSafeConfig = + | ConnectSafeConfigWithSafeAddress + | ConnectSafeConfigWithPredictedSafe + +export interface CreateTransactionProps { + safeContract: Safe_V1_3_0, + signer: Signer, + multiSendCallOnlyContractAddress: string, + multiSendContractAddress: string, + /** safeTransactionData - The transaction or transaction array to process */ + safeTransactionData: SafeTransactionDataPartial | MetaTransactionData[] + /** options - The transaction array optional properties */ + options?: SafeTransactionOptionalProps + /** onlyCalls - Forces the execution of the transaction array with MultiSendCallOnly contract */ + onlyCalls?: boolean +} + +type StandardizeSafeTxDataWithSafeContractProps = { + /** safeContract - The Safe contract to use */ + safeContract: Safe_V1_3_0 + /** predictedSafe - The configuration of the Safe that is not yet deployed */ + predictedSafe?: never +} + +type StandardizeSafeTxDataWithPredictedSafeProps = { + /** safeContract - The Safe contract to use */ + safeContract?: never + /** predictedSafe - The configuration of the Safe that is not yet deployed */ + predictedSafe: PredictedSafeProps +} + +interface StandardizeSafeTransactionData { + signer: Signer; + /** tx - Safe transaction */ + tx: SafeTransactionDataPartial + /** contractNetworks - Contract network configuration */ + contractNetworks?: ContractNetworksConfig +} + +export type StandardizeSafeTxDataWithSafeContract = StandardizeSafeTransactionData & + StandardizeSafeTxDataWithSafeContractProps +export type StandardizeSafeTxDataWithPredictedSafe = StandardizeSafeTransactionData & + StandardizeSafeTxDataWithPredictedSafeProps +export type StandardizeSafeTransactionDataProps = + | StandardizeSafeTxDataWithSafeContract + | StandardizeSafeTxDataWithPredictedSafe + + +export interface GetContractInstanceProps { + signer: Signer + safeVersion: SafeVersion + customContracts?: ContractNetworkConfig + } \ No newline at end of file diff --git a/apps/dapp/src/safe/sdk/utils/utils.ts b/apps/dapp/src/safe/sdk/utils/utils.ts new file mode 100644 index 000000000..787159bb5 --- /dev/null +++ b/apps/dapp/src/safe/sdk/utils/utils.ts @@ -0,0 +1,342 @@ +import { Signer } from '@ethersproject/abstract-signer'; +import { + MetaTransactionData, + OperationType, + SafeMultisigTransactionResponse, + SafeTransaction, + SafeTransactionData, + SafeTransactionDataPartial, + SafeVersion, +} from '@safe-global/safe-core-sdk-types'; +import { SAFE_FEATURES, hasSafeFeature } from './safeVersions'; +import { arrayify } from '@ethersproject/bytes'; +import { pack as solidityPack } from '@ethersproject/solidity'; +import EthSafeTransaction from '../transactions/SafeTransaction'; +import { + CreateTransactionProps, + StandardizeSafeTransactionDataProps, +} from './types'; +import { estimateGas } from '../transactions/gas'; +import { DEFAULT_SAFE_VERSION } from '../contracts/config'; +import { EthSafeSignature } from '../signatures/SafeSignature'; +import { Gnosis_safe as Safe_V1_3_0 } from 'types/typechain/@safe-global/safe-deployments/v1.3.0/Gnosis_safe'; +import { getMultiSendCallOnlyContract, getMultiSendCallOnlyContractDeploymentDetails, getMultiSendContract, getMultiSendContractDeploymentDetails, getSafeContract } from '../contracts/safeDeploymentContracts'; + +export const ZERO_ADDRESS = `0x${'0'.repeat(40)}` + +export function isSafeMultisigTransactionResponse( + safeTransaction: SafeTransaction | SafeMultisigTransactionResponse +): safeTransaction is SafeMultisigTransactionResponse { + return (safeTransaction as SafeMultisigTransactionResponse).isExecuted !== undefined; +} + +/** + * Converts a transaction from type SafeMultisigTransactionResponse to type SafeTransaction + * + * @param serviceTransactionResponse - The transaction to convert + * @returns The converted transaction with type SafeTransaction + */ +export const toSafeTransactionType = async ( + safeContract: Safe_V1_3_0, + signer: Signer, + serviceTransactionResponse: SafeMultisigTransactionResponse +): Promise => { + const safeTransactionData: SafeTransactionDataPartial = { + to: serviceTransactionResponse.to, + value: serviceTransactionResponse.value, + data: serviceTransactionResponse.data || '0x', + operation: serviceTransactionResponse.operation, + safeTxGas: serviceTransactionResponse.safeTxGas.toString(), + baseGas: serviceTransactionResponse.baseGas.toString(), + gasPrice: serviceTransactionResponse.gasPrice, + gasToken: serviceTransactionResponse.gasToken, + refundReceiver: serviceTransactionResponse.refundReceiver, + nonce: serviceTransactionResponse.nonce, + }; + const safeVersion = (await safeContract.VERSION()) as SafeVersion; + const multiSendDeploymentDetails = await getMultiSendContractDeploymentDetails(safeVersion, await signer.getChainId()); + const multiSendCallOnlyDeploymentDetails = await getMultiSendCallOnlyContractDeploymentDetails(safeVersion, await signer.getChainId()); + const safeTransaction = await createTransaction({ + safeContract, + signer, + multiSendContractAddress: multiSendDeploymentDetails.defaultAddress, + multiSendCallOnlyContractAddress: multiSendCallOnlyDeploymentDetails.defaultAddress, + safeTransactionData, + }); + serviceTransactionResponse.confirmations?.map((confirmation) => { + const signature = new EthSafeSignature(confirmation.owner, confirmation.signature); + safeTransaction.addSignature(signature); + }); + return safeTransaction; +}; + +/** + * Returns a Safe transaction ready to be signed by the owners. + * + * @param createTransactionProps - The createTransaction props + * @returns The Safe transaction + * @throws "Invalid empty array of transactions" + */ +const createTransaction = async ({ + safeContract, + signer, + safeTransactionData, + onlyCalls = false, + options, +}: CreateTransactionProps): Promise => { + const safeVersion = await safeContract.VERSION(); + if (!hasSafeFeature(SAFE_FEATURES.ACCOUNT_ABSTRACTION, safeVersion)) { + throw new Error('Account Abstraction functionality is not available for Safes with version lower than v1.3.0'); + } + + if (isMetaTransactionArray(safeTransactionData) && safeTransactionData.length === 0) { + throw new Error('Invalid empty array of transactions'); + } + + let newTransaction: SafeTransactionDataPartial; + if (isMetaTransactionArray(safeTransactionData) && safeTransactionData.length > 1) { + const multiSendContract = onlyCalls + ? getMultiSendCallOnlyContract({signer, safeVersion: DEFAULT_SAFE_VERSION}) + : getMultiSendContract({signer, safeVersion: DEFAULT_SAFE_VERSION}); + + const multiSendData = encodeMultiSendData(safeTransactionData.map(standardizeMetaTransactionData)); + + const multiSendTransaction = { + ...options, + to: (await multiSendContract).address, + value: '0', + data: (await multiSendContract).interface.encodeFunctionData('multiSend', [multiSendData]), + operation: OperationType.DelegateCall, + }; + newTransaction = multiSendTransaction; + } else { + newTransaction = isMetaTransactionArray(safeTransactionData) + ? { ...options, ...safeTransactionData[0] } + : safeTransactionData; + } + + if (!safeContract) { + throw new Error('Safe is not deployed'); + } + return new EthSafeTransaction( + await standardizeSafeTransactionData({ + safeContract, + signer, + tx: newTransaction, + }) + ); +}; + +/** + * Copies a Safe transaction + * + * @param safeTransaction - The Safe transaction + * @returns The new Safe transaction + */ +export const copyTransaction = async ( + safeContract: Safe_V1_3_0, + signer: Signer, + safeTransaction: SafeTransaction +): Promise => { + const safeVersion = (await safeContract.VERSION()) as SafeVersion; + const multiSendDeploymentDetails = await getMultiSendContractDeploymentDetails(safeVersion, await signer.getChainId()); + const multiSendCallOnlyDeploymentDetails = await getMultiSendCallOnlyContractDeploymentDetails(safeVersion, await signer.getChainId()); + const signedSafeTransaction = await createTransaction({ + safeContract, + signer, + multiSendContractAddress: multiSendDeploymentDetails.defaultAddress, + multiSendCallOnlyContractAddress: multiSendCallOnlyDeploymentDetails.defaultAddress, + safeTransactionData: safeTransaction.data, + }); + safeTransaction.signatures.forEach((signature) => { + signedSafeTransaction.addSignature(signature); + }); + return signedSafeTransaction; +}; + +/** + * Returns the transaction hash of a Safe transaction. + * + * @param safeTransaction - The Safe transaction + * @returns The transaction hash of the Safe transaction + */ +export const getTransactionHash = async ( + safeContract: Safe_V1_3_0, + safeTransaction: SafeTransaction +): Promise => { + if (!safeContract) { + throw new Error('Safe is not deployed'); + } + const sftd = safeTransaction.data; + const txHash = await safeContract.getTransactionHash( + sftd.to, + sftd.value, + sftd.data, + sftd.operation, + sftd.safeTxGas, + sftd.baseGas, + sftd.gasPrice, + sftd.gasToken, + sftd.refundReceiver, + sftd.nonce + ); + return txHash; +}; + +/** + * Returns a list of owners who have approved a specific Safe transaction. + * + * @param txHash - The Safe transaction hash + * @returns The list of owners + */ +export const getOwnersWhoApprovedTx = async ( + safeContract: Safe_V1_3_0, + txHash: string +): Promise => { + if (!safeContract) { + throw new Error('Safe is not deployed'); + } + + const owners = await getOwners(safeContract); + const ownersWhoApproved: string[] = []; + for (const owner of owners) { + const approved = await safeContract.approvedHashes(owner, txHash); + if (approved.gt(0)) { + ownersWhoApproved.push(owner); + } + } + return ownersWhoApproved; +}; + +/** + * Returns the list of Safe owner accounts. + * + * @returns The list of owners + */ +export const getOwners = async (safeContract: Safe_V1_3_0): Promise => { + if (!safeContract) { + throw new Error('Safe is not deployed'); + } + const owners = await safeContract.getOwners(); + return [...owners]; +}; + +/** + * Returns the Safe threshold. + * + * @returns The Safe threshold + */ +export const getThreshold = async (safeContract: Safe_V1_3_0): Promise => { + if (!safeContract) { + throw new Error('Safe is not deployed'); + } + return (await safeContract.getThreshold()).toNumber(); +}; + +export function isMetaTransactionArray( + safeTransactions: SafeTransactionDataPartial | MetaTransactionData[] +): safeTransactions is MetaTransactionData[] { + return (safeTransactions as MetaTransactionData[])?.length !== undefined; +} + +function encodeMultiSendData(txs: MetaTransactionData[]): string { + return '0x' + txs.map((tx) => encodeMetaTransaction(tx)).join(''); +} + +function encodeMetaTransaction(tx: MetaTransactionData): string { + const data = arrayify(tx.data); + const encoded = solidityPack( + ['uint8', 'address', 'uint256', 'uint256', 'bytes'], + [tx.operation, tx.to, tx.value, data.length, data] + ); + return encoded.slice(2); +} + +export async function standardizeSafeTransactionData({ + safeContract, + signer, + tx, +}: StandardizeSafeTransactionDataProps): Promise { + const standardizedTxs = { + to: tx.to, + value: tx.value, + data: tx.data, + operation: tx.operation ?? OperationType.Call, + baseGas: tx.baseGas ?? '0', + gasPrice: tx.gasPrice ?? '0', + gasToken: tx.gasToken || ZERO_ADDRESS, + refundReceiver: tx.refundReceiver || ZERO_ADDRESS, + nonce: tx.nonce ?? (safeContract ? (await safeContract.nonce()).toNumber() : 0), + }; + + if (typeof tx.safeTxGas !== 'undefined') { + return { + ...standardizedTxs, + safeTxGas: tx.safeTxGas, + }; + } + + if (!safeContract) { + throw new Error('Safe is not deployed'); + } + const safeVersion = (await safeContract.VERSION()) as SafeVersion; + + if (!safeContract) { + throw new Error('Safe is not deployed'); + } + + const safeTxGas = await estimateGas( + safeVersion, + safeContract, + signer, + standardizedTxs.to, + standardizedTxs.value, + standardizedTxs.data, + standardizedTxs.operation + ); + return { + ...standardizedTxs, + safeTxGas, + }; +} + +export function sameString(str1: string, str2: string): boolean { + return str1.toLowerCase() === str2.toLowerCase(); +} + + +export function standardizeMetaTransactionData( + tx: SafeTransactionDataPartial +): MetaTransactionData { + const standardizedTxs: MetaTransactionData = { + ...tx, + operation: tx.operation ?? OperationType.Call + } + return standardizedTxs +} + +/** + * Returns the Safe Transaction encoded + * + * @async + * @param {SafeTransaction} safeTransaction - The Safe transaction to be encoded. + * @returns {Promise} The encoded transaction + * + */ +export const getEncodedTransaction = async(safeContract: Safe_V1_3_0, safeTransaction: SafeTransaction): Promise => { + + const encodedTransaction: string = safeContract.interface.encodeFunctionData('execTransaction', [ + safeTransaction.data.to, + safeTransaction.data.value, + safeTransaction.data.data, + safeTransaction.data.operation, + safeTransaction.data.safeTxGas, + safeTransaction.data.baseGas, + safeTransaction.data.gasPrice, + safeTransaction.data.gasToken, + safeTransaction.data.refundReceiver, + safeTransaction.encodedSignatures() + ]) as string + + return encodedTransaction +} \ No newline at end of file diff --git a/apps/dapp/tsconfig.json b/apps/dapp/tsconfig.json index ad5a521a8..8a6504735 100644 --- a/apps/dapp/tsconfig.json +++ b/apps/dapp/tsconfig.json @@ -20,6 +20,7 @@ "data/*": ["./data/*"], "types/*": ["./types/*"], "constants/*": ["./constants/*"], + "safe/*": ["./safe/*"], }, }, "include": ["**/*.ts", "**/*.tsx","**/*.json", "api/ping.js", "api/geoblock.js"], diff --git a/apps/dapp/vite.config.ts b/apps/dapp/vite.config.ts index 0caa2e86e..8a330f933 100644 --- a/apps/dapp/vite.config.ts +++ b/apps/dapp/vite.config.ts @@ -75,6 +75,7 @@ export default defineConfig({ data: path.resolve(__dirname, 'src/data'), types: path.resolve(__dirname, 'src/types'), constants: path.resolve(__dirname, 'src/constants'), + safe: path.resolve(__dirname, 'src/safe'), }, }, envPrefix: 'VITE', diff --git a/protocol/scripts/deploys/sepolia/v2/contract-addresses.ts b/protocol/scripts/deploys/sepolia/v2/contract-addresses.ts index bc79daaa5..bc7a2440b 100644 --- a/protocol/scripts/deploys/sepolia/v2/contract-addresses.ts +++ b/protocol/scripts/deploys/sepolia/v2/contract-addresses.ts @@ -113,7 +113,7 @@ const V2_DEPLOYED_CONTRACTS: {[key: string]: ContractAddresses} = { TEMPLE_TOKEN: '0x64a925B0fA211c44337148C0807f959Bd44b0B67', CIRCUIT_BREAKER_PROXY: '0x08F542783f076cA905EEccC6a987629BE5017a4C', GNOSIS_SAFE_GUARD: '0x9A792288BE7d6Be936882e00D8C3a2b05a921e65', - EXECUTOR_MSIG: '0xF8Ab0fF572e48059c45eF3fa804e5A369d2b9b2B', + EXECUTOR_MSIG: '0x7d1e9012aA41278349791f29C2cdaa3DF4ceDcEd', RESCUER_MSIG: '0x8dbe2E7Cab43F00fce7fFe90769b87456692CE46', }, TREASURY_RESERVES_VAULT: { @@ -138,7 +138,7 @@ const V2_DEPLOYED_CONTRACTS: {[key: string]: ContractAddresses} = { ADDRESS: '0x82ce000a51E8474378f7b555bcC4de5992052452', POOL_HELPER: '0xbfC24c9d7D57C413618CE11cea1e313a2E8D9e1d', AURA_STAKING: '0xa60eB5CFb98BB7237751077baD3addd6d3C61803', - FEE_COLLECTOR: '0xF8Ab0fF572e48059c45eF3fa804e5A369d2b9b2B', + FEE_COLLECTOR: '0x7d1e9012aA41278349791f29C2cdaa3DF4ceDcEd', BPT_TOKEN: '0x825250921A357eE1e5411D33B88C83bfc0f34A2A', POOL_ID: '0x825250921a357ee1e5411d33b88c83bfc0f34a2a000200000000000000000011', }, @@ -146,19 +146,19 @@ const V2_DEPLOYED_CONTRACTS: {[key: string]: ContractAddresses} = { STRATEGIES: { DSR_BASE_STRATEGY: { ADDRESS: '0x472C7cDb6E730ff499E118dE6260c6b44c61d7bf', - EXECUTOR_MSIG: '0xF8Ab0fF572e48059c45eF3fa804e5A369d2b9b2B', + EXECUTOR_MSIG: '0x7d1e9012aA41278349791f29C2cdaa3DF4ceDcEd', RESCUER_MSIG: '0x8dbe2E7Cab43F00fce7fFe90769b87456692CE46', // No circuit breakers for DSR base strategy }, TEMPLE_BASE_STRATEGY: { ADDRESS: '0xECe4ff1bd589b488350557A5C36D823C7B47E82F', - EXECUTOR_MSIG: '0xF8Ab0fF572e48059c45eF3fa804e5A369d2b9b2B', + EXECUTOR_MSIG: '0x7d1e9012aA41278349791f29C2cdaa3DF4ceDcEd', RESCUER_MSIG: '0x8dbe2E7Cab43F00fce7fFe90769b87456692CE46', // No circuit breakers for Temple base strategy }, GNOSIS_SAFE_STRATEGY_TEMPLATE: { ADDRESS: '0x76D3d175f18FAc6e390a33bf54c6477AcE6697e2', - EXECUTOR_MSIG: '0xF8Ab0fF572e48059c45eF3fa804e5A369d2b9b2B', + EXECUTOR_MSIG: '0x7d1e9012aA41278349791f29C2cdaa3DF4ceDcEd', RESCUER_MSIG: '0x8dbe2E7Cab43F00fce7fFe90769b87456692CE46', UNDERLYING_GNOSIS_SAFE: '0x81960c465605cddD9772a8653111D4aBE580Ce1e', // The deployer wallet CIRCUIT_BREAKERS: { @@ -168,7 +168,7 @@ const V2_DEPLOYED_CONTRACTS: {[key: string]: ContractAddresses} = { }, RAMOS_STRATEGY: { ADDRESS: '0xB9507b59f91FF320631d30f774142631b30C537A', - EXECUTOR_MSIG: '0xF8Ab0fF572e48059c45eF3fa804e5A369d2b9b2B', + EXECUTOR_MSIG: '0x7d1e9012aA41278349791f29C2cdaa3DF4ceDcEd', RESCUER_MSIG: '0x8dbe2E7Cab43F00fce7fFe90769b87456692CE46', CIRCUIT_BREAKERS: { DAI: '0xcF4fdC6d455F33A6236df79aAA82c58E173f7fB5', @@ -177,7 +177,7 @@ const V2_DEPLOYED_CONTRACTS: {[key: string]: ContractAddresses} = { }, TLC_STRATEGY: { ADDRESS: '0x415A9B41700AC645d9C22F2499a6E853b625F792', - EXECUTOR_MSIG: '0xF8Ab0fF572e48059c45eF3fa804e5A369d2b9b2B', + EXECUTOR_MSIG: '0x7d1e9012aA41278349791f29C2cdaa3DF4ceDcEd', RESCUER_MSIG: '0x8dbe2E7Cab43F00fce7fFe90769b87456692CE46', }, }, diff --git a/yarn.lock b/yarn.lock index 8d6d60dc9..49f728f1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20,6 +20,16 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@apidevtools/json-schema-ref-parser@9.0.9": + version "9.0.9" + resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b" + integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w== + dependencies: + "@jsdevtools/ono" "^7.1.3" + "@types/json-schema" "^7.0.6" + call-me-maybe "^1.0.1" + js-yaml "^4.1.0" + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -2102,7 +2112,7 @@ "@ethersproject/properties" "^5.5.0" "@ethersproject/transactions" "^5.5.0" -"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.0.0", "@ethersproject/contracts@^5.4.0": +"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.0.0", "@ethersproject/contracts@^5.4.0", "@ethersproject/contracts@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== @@ -2842,6 +2852,11 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jsdevtools/ono@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" + integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== + "@ledgerhq/devices@^4.74.2", "@ledgerhq/devices@^4.78.0": version "4.78.0" resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-4.78.0.tgz#149b572f0616096e2bd5eb14ce14d0061c432be6" @@ -3443,6 +3458,24 @@ "@safe-global/safe-gateway-typescript-sdk" "^3.5.3" viem "^1.0.0" +"@safe-global/safe-core-sdk-types@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-types/-/safe-core-sdk-types-2.3.0.tgz#e3be109e58a2d224d1b89052563b04f3efed4bec" + integrity sha512-dU0KkDV1KJNf11ajbUjWiSi4ygdyWfhk1M50lTJWUdCn1/2Bsb/hICM8LoEk6DCoFumxaoCet02SmYakXsW2CA== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/contracts" "^5.7.0" + "@safe-global/safe-deployments" "^1.26.0" + web3-core "^1.8.1" + web3-utils "^1.8.1" + +"@safe-global/safe-deployments@^1.26.0": + version "1.29.0" + resolved "https://registry.yarnpkg.com/@safe-global/safe-deployments/-/safe-deployments-1.29.0.tgz#72091773dccdea67d4a0066eeaaa816613b43cca" + integrity sha512-rXTktZblfklQyPe2JLK7GtXW/jH8htE6oP9MQHpVU5K/98OLkR4ApLAzlJscQEcyCaK+XOQunOk/gQYK1M2IpQ== + dependencies: + semver "^7.3.7" + "@safe-global/safe-gateway-typescript-sdk@^3.5.3": version "3.10.0" resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.10.0.tgz#a252ac5a61487d7785c44f1ed7e899ccd5aa9038" @@ -4558,7 +4591,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^17", "@types/react@^17.0.0": +"@types/react@*", "@types/react@17.0.40", "@types/react@^17", "@types/react@^17.0.0": version "17.0.40" resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.40.tgz#dc010cee6254d5239a138083f3799a16638e6bad" integrity sha512-UrXhD/JyLH+W70nNSufXqMZNuUD2cXHu6UjCllC6pmOQgBX4SGXOH8fjRka0O0Ee0HrFxapDD8Bwn81Kmiz6jQ== @@ -4599,6 +4632,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.1.tgz#0480eeb7221eb9bc398ad7432c9d7e14b1a5a367" integrity sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg== +"@types/semver@^7.5.6": + version "7.5.7" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.7.tgz#326f5fdda70d13580777bcaa1bc6fa772a5aef0e" + integrity sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg== + "@types/sinonjs__fake-timers@8.1.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" @@ -5396,7 +5434,7 @@ abitype@0.9.3: resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.9.3.tgz#294d25288ee683d72baf4e1fed757034e3c8c277" integrity sha512-dz4qCQLurx97FQhnb/EIYTk/ldQ+oafEDUqC0VVIeQS1Q48/YWt/9YNfMmp9SLFqN41ktxny3c8aYxHjmFIB/w== -abortcontroller-polyfill@^1.7.3: +abortcontroller-polyfill@^1.7.3, abortcontroller-polyfill@^1.7.5: version "1.7.5" resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== @@ -7464,6 +7502,11 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +call-me-maybe@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" + integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -7501,7 +7544,7 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0, camelcase@^6.2.0: +camelcase@^6.0.0, camelcase@^6.2.0, camelcase@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -8100,6 +8143,11 @@ commander@9.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-9.1.0.tgz#a6b263b2327f2e188c6402c42623327909f2dbec" integrity sha512-i0/MaqBtdbnJ4XQs4Pmyb+oFQl+q0lsAmokVUH92SlSw4fkeAcG3bVon+Qt7hmtF+u3Het6o4VgrcY3qAoEB6w== +commander@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" + integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== + commander@^2.18.0, commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -8566,7 +8614,7 @@ cross-fetch@3.1.5: dependencies: node-fetch "2.6.7" -cross-fetch@4.0.0: +cross-fetch@4.0.0, cross-fetch@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== @@ -11318,7 +11366,7 @@ ethers@^4.0.32, ethers@^4.0.40, ethers@^4.0.45: uuid "2.0.1" xmlhttprequest "1.8.0" -ethers@^5.0.13, ethers@^5.7.1, ethers@^5.7.2: +ethers@^5.0.13, ethers@^5.7.1, ethers@^5.7.2, ethers@~5.7.0: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -12084,6 +12132,15 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@^11.1.1: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^4.0.2, fs-extra@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -14106,6 +14163,13 @@ json-rpc-random-id@^1.0.0, json-rpc-random-id@^1.0.1: resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== +json-schema-ref-parser@^9.0.9: + version "9.0.9" + resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#66ea538e7450b12af342fa3d5b8458bc1e1e013f" + integrity sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q== + dependencies: + "@apidevtools/json-schema-ref-parser" "9.0.9" + json-schema-to-ts@1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/json-schema-to-ts/-/json-schema-to-ts-1.6.4.tgz#63e4fe854dff093923be9e8b59b39ee9a7971ba4" @@ -16077,6 +16141,17 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +openapi-typescript-codegen@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/openapi-typescript-codegen/-/openapi-typescript-codegen-0.25.0.tgz#0cb028f54b33b0a63bd9da3756c1c41b4e1a70e2" + integrity sha512-nN/TnIcGbP58qYgwEEy5FrAAjePcYgfMaCe3tsmYyTgI3v4RR9v8os14L+LEWDvV50+CmqiyTzRkKKtJeb6Ybg== + dependencies: + camelcase "^6.3.0" + commander "^11.0.0" + fs-extra "^11.1.1" + handlebars "^4.7.7" + json-schema-ref-parser "^9.0.9" + "openzeppelin-solidity-2.3.0@npm:openzeppelin-solidity@2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.3.0.tgz#1ab7b4cc3782a5472ed61eb740c56a8bfdd74119" @@ -20557,6 +20632,14 @@ web3-core-helpers@1.10.0: web3-eth-iban "1.10.0" web3-utils "1.10.0" +web3-core-helpers@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.10.3.tgz#f2db40ea57e888795e46f229b06113b60bcd671c" + integrity sha512-Yv7dQC3B9ipOc5sWm3VAz1ys70Izfzb8n9rSiQYIPjpqtJM+3V4EeK6ghzNR6CO2es0+Yu9CtCkw0h8gQhrTxA== + dependencies: + web3-eth-iban "1.10.3" + web3-utils "1.10.3" + web3-core-helpers@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" @@ -20577,6 +20660,17 @@ web3-core-method@1.10.0: web3-core-subscriptions "1.10.0" web3-utils "1.10.0" +web3-core-method@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.10.3.tgz#63f16310ccab4eec8eca0a337d534565c2ba8d33" + integrity sha512-VZ/Dmml4NBmb0ep5PTSg9oqKoBtG0/YoMPei/bq/tUdlhB2dMB79sbeJPwx592uaV0Vpk7VltrrrBv5hTM1y4Q== + dependencies: + "@ethersproject/transactions" "^5.6.2" + web3-core-helpers "1.10.3" + web3-core-promievent "1.10.3" + web3-core-subscriptions "1.10.3" + web3-utils "1.10.3" + web3-core-method@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" @@ -20596,6 +20690,13 @@ web3-core-promievent@1.10.0: dependencies: eventemitter3 "4.0.4" +web3-core-promievent@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.10.3.tgz#9765dd42ce6cf2dc0a08eaffee607b855644f290" + integrity sha512-HgjY+TkuLm5uTwUtaAfkTgRx/NzMxvVradCi02gy17NxDVdg/p6svBHcp037vcNpkuGeFznFJgULP+s2hdVgUQ== + dependencies: + eventemitter3 "4.0.4" + web3-core-promievent@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" @@ -20614,6 +20715,17 @@ web3-core-requestmanager@1.10.0: web3-providers-ipc "1.10.0" web3-providers-ws "1.10.0" +web3-core-requestmanager@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.10.3.tgz#c34ca8e998a18d6ca3fa7f7a11d4391da401c987" + integrity sha512-VT9sKJfgM2yBOIxOXeXiDuFMP4pxzF6FT+y8KTLqhDFHkbG3XRe42Vm97mB/IvLQCJOmokEjl3ps8yP1kbggyw== + dependencies: + util "^0.12.5" + web3-core-helpers "1.10.3" + web3-providers-http "1.10.3" + web3-providers-ipc "1.10.3" + web3-providers-ws "1.10.3" + web3-core-requestmanager@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" @@ -20633,6 +20745,14 @@ web3-core-subscriptions@1.10.0: eventemitter3 "4.0.4" web3-core-helpers "1.10.0" +web3-core-subscriptions@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.10.3.tgz#58768cd72a9313252ef05dc52c09536f009a9479" + integrity sha512-KW0Mc8sgn70WadZu7RjQ4H5sNDJ5Lx8JMI3BWos+f2rW0foegOCyWhRu33W1s6ntXnqeBUw5rRCXZRlA3z+HNA== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.10.3" + web3-core-subscriptions@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" @@ -20668,6 +20788,19 @@ web3-core@1.2.11: web3-core-requestmanager "1.2.11" web3-utils "1.2.11" +web3-core@^1.8.1: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.10.3.tgz#4aeb8f4b0cb5775d9fa4edf1127864743f1c3ae3" + integrity sha512-Vbk0/vUNZxJlz3RFjAhNNt7qTpX8yE3dn3uFxfX5OHbuon5u65YEOd3civ/aQNW745N0vGUlHFNxxmn+sG9DIw== + dependencies: + "@types/bn.js" "^5.1.1" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.10.3" + web3-core-method "1.10.3" + web3-core-requestmanager "1.10.3" + web3-utils "1.10.3" + web3-eth-abi@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.10.0.tgz#53a7a2c95a571e205e27fd9e664df4919483cce1" @@ -20792,6 +20925,14 @@ web3-eth-iban@1.10.0: bn.js "^5.2.1" web3-utils "1.10.0" +web3-eth-iban@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.10.3.tgz#91d458e5400195edc883a0d4383bf1cecd17240d" + integrity sha512-ZCfOjYKAjaX2TGI8uif5ah+J3BYFuo+47JOIV1RIz2l7kD9VfnxvRH5UiQDRyMALQC7KFd2hUqIEtHklapNyKA== + dependencies: + bn.js "^5.2.1" + web3-utils "1.10.3" + web3-eth-iban@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" @@ -20943,6 +21084,16 @@ web3-providers-http@1.10.0: es6-promise "^4.2.8" web3-core-helpers "1.10.0" +web3-providers-http@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.10.3.tgz#d8166ee89db82d37281ea9e15c5882a2d7928755" + integrity sha512-6dAgsHR3MxJ0Qyu3QLFlQEelTapVfWNTu5F45FYh8t7Y03T1/o+YAkVxsbY5AdmD+y5bXG/XPJ4q8tjL6MgZHw== + dependencies: + abortcontroller-polyfill "^1.7.5" + cross-fetch "^4.0.0" + es6-promise "^4.2.8" + web3-core-helpers "1.10.3" + web3-providers-http@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" @@ -20959,6 +21110,14 @@ web3-providers-ipc@1.10.0: oboe "2.1.5" web3-core-helpers "1.10.0" +web3-providers-ipc@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.10.3.tgz#a7e015957fc037d8a87bd4b6ae3561c1b1ad1f46" + integrity sha512-vP5WIGT8FLnGRfswTxNs9rMfS1vCbMezj/zHbBe/zB9GauBRTYVrUo2H/hVrhLg8Ut7AbsKZ+tCJ4mAwpKi2hA== + dependencies: + oboe "2.1.5" + web3-core-helpers "1.10.3" + web3-providers-ipc@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" @@ -20977,6 +21136,15 @@ web3-providers-ws@1.10.0: web3-core-helpers "1.10.0" websocket "^1.0.32" +web3-providers-ws@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.10.3.tgz#03c84958f9da251349cd26fd7a4ae567e3af6caa" + integrity sha512-/filBXRl48INxsh6AuCcsy4v5ndnTZ/p6bl67kmO9aK1wffv7CT++DrtclDtVMeDGCgB3van+hEf9xTAVXur7Q== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.10.3" + websocket "^1.0.32" + web3-providers-ws@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" @@ -21034,6 +21202,20 @@ web3-utils@1.10.2, web3-utils@^1.0.0-beta.31, web3-utils@^1.2.1, web3-utils@^1.3 randombytes "^2.1.0" utf8 "3.0.0" +web3-utils@1.10.3, web3-utils@^1.8.1: + version "1.10.3" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.3.tgz#f1db99c82549c7d9f8348f04ffe4e0188b449714" + integrity sha512-OqcUrEE16fDBbGoQtZXWdavsPzbGIDc5v3VrRTZ0XrIpefC/viZ1ZU9bGEemazyS0catk/3rkOOxpzTfY+XsyQ== + dependencies: + "@ethereumjs/util" "^8.1.0" + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereum-cryptography "^2.1.2" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + web3-utils@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" @@ -21630,3 +21812,10 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zksync-web3@^0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.17.1.tgz#809c3b31295c29aae924ec2fe47f87701b539012" + integrity sha512-jMV4gfAQyehkIbNs81i4uvccHLe+XBu/tNPFb0Rm38pXccWY5VXzVE6XWS0dBiHlMfjdfUGn/sxwzJbWZDGYGQ== + dependencies: + ethers "~5.7.0"