Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Merge pull request #31 from radicle-dev/cloudhead/safe-set-name
Alexis Sellier committed 4 years ago
commit 0b6f3a4044f99772b9b19d34b7de53354e1a2145
parent cf5ce069c448c2e2dcc32acf926552c37e12bb89
14 files changed +1050 -53
modified index.html
@@ -10,7 +10,11 @@
    <link rel="icon" href="/favicon.svg" type="image/svg+xml">
    <link rel="preload" href="/fonts/Inter-Regular.woff" as="font" type="font/woff">
    <link rel="preload" href="/fonts/Inter-SemiBold.otf" as="font" type="font/otf">
-

+
    <script type="text/javascript">
+
      // Workaround to get `global` to work in old-school transitive
+
      // dependencies.
+
      window.global = window;
+
    </script>
    <title>Radicle Interface</title>
  </head>
  <body>
modified package-lock.json
@@ -5,7 +5,12 @@
  "packages": {
    "": {
      "dependencies": {
+
        "@gnosis.pm/safe-core-sdk": "^0.2.0",
+
        "@gnosis.pm/safe-core-sdk-types": "^0.1.1",
+
        "@gnosis.pm/safe-service-client": "^0.1.0-alpha.0",
+
        "@stardazed/streams": "^3.1.0",
        "@types/marked": "^2.0.3",
+
        "buffer": "^6.0.3",
        "ethereum-blockies": "^0.1.1",
        "ethers": "^5.0.31",
        "marked": "^2.0.7",
@@ -820,6 +825,29 @@
        "@ethersproject/strings": "^5.3.0"
      }
    },
+
    "node_modules/@gnosis.pm/safe-core-sdk": {
+
      "version": "0.2.0",
+
      "resolved": "https://registry.npmjs.org/@gnosis.pm/safe-core-sdk/-/safe-core-sdk-0.2.0.tgz",
+
      "integrity": "sha512-HofU9KvbdMyoblvVyjTAEGNjdte4CamIfbZ5VgmAZhm2j8DwVJ6kqqRjGVar36eOv3sfozuJmnZwkPMM9BaV8Q==",
+
      "dependencies": {
+
        "@gnosis.pm/safe-core-sdk-types": "^0.1.1",
+
        "ethereumjs-util": "^7.0.10"
+
      }
+
    },
+
    "node_modules/@gnosis.pm/safe-core-sdk-types": {
+
      "version": "0.1.1",
+
      "resolved": "https://registry.npmjs.org/@gnosis.pm/safe-core-sdk-types/-/safe-core-sdk-types-0.1.1.tgz",
+
      "integrity": "sha512-PghXGDaI5Foq37nZGmI90U2OKMeGtxh5KqkDqou9aFHwGVa/nf9HRQPxG9/XUzcyfe9OlKttDlJnR3XnC3dSDw=="
+
    },
+
    "node_modules/@gnosis.pm/safe-service-client": {
+
      "version": "0.1.0-alpha.0",
+
      "resolved": "https://registry.npmjs.org/@gnosis.pm/safe-service-client/-/safe-service-client-0.1.0-alpha.0.tgz",
+
      "integrity": "sha512-Ld8B7VMAjjWMrywa+SNrLw+w4qJrvd6OEeLUkUTfFK6yDW9ybbfy6QO6bUMgOP4WhgUdRnTVpm/526DcddkifA==",
+
      "dependencies": {
+
        "@gnosis.pm/safe-core-sdk-types": "^0.1.0",
+
        "axios": "^0.21.1"
+
      }
+
    },
    "node_modules/@multiformats/base-x": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz",
@@ -882,6 +910,11 @@
      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
      "dev": true
    },
+
    "node_modules/@stardazed/streams": {
+
      "version": "3.1.0",
+
      "resolved": "https://registry.npmjs.org/@stardazed/streams/-/streams-3.1.0.tgz",
+
      "integrity": "sha512-+fNbzyPb65oknwBgMjJrfs7dPXIJTDgnrFQcLI9+tpYTvHgrxwlqMm8geV4NA640qp+udIenWQDLU+hsB06Vcw=="
+
    },
    "node_modules/@sveltejs/vite-plugin-svelte": {
      "version": "1.0.0-next.10",
      "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.10.tgz",
@@ -932,6 +965,14 @@
      "integrity": "sha512-EBrpH2iXXfaf/9z81koiDYkp2mlwW2XzFcAqn6qh7VKyP8zBvHHAQzNhY+W9vH5arAjmGAm5g8ElWq6YmXm3ig==",
      "dev": true
    },
+
    "node_modules/@types/bn.js": {
+
      "version": "5.1.0",
+
      "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz",
+
      "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==",
+
      "dependencies": {
+
        "@types/node": "*"
+
      }
+
    },
    "node_modules/@types/json-schema": {
      "version": "7.0.7",
      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
@@ -948,6 +989,14 @@
      "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz",
      "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww=="
    },
+
    "node_modules/@types/pbkdf2": {
+
      "version": "3.1.0",
+
      "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz",
+
      "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==",
+
      "dependencies": {
+
        "@types/node": "*"
+
      }
+
    },
    "node_modules/@types/pug": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.4.tgz",
@@ -961,6 +1010,14 @@
        "@types/node": "*"
      }
    },
+
    "node_modules/@types/secp256k1": {
+
      "version": "4.0.2",
+
      "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.2.tgz",
+
      "integrity": "sha512-QMg+9v0bbNJ2peLuHRWxzmy0HRJIG6gFZNhaRSp7S3ggSbCCxiqQB2/ybvhXyhHOCequpNkrx7OavNhrWOsW0A==",
+
      "dependencies": {
+
        "@types/node": "*"
+
      }
+
    },
    "node_modules/@typescript-eslint/eslint-plugin": {
      "version": "4.26.1",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.26.1.tgz",
@@ -1242,12 +1299,47 @@
        "node": ">=8"
      }
    },
+
    "node_modules/axios": {
+
      "version": "0.21.1",
+
      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
+
      "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
+
      "dependencies": {
+
        "follow-redirects": "^1.10.0"
+
      }
+
    },
    "node_modules/balanced-match": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
      "dev": true
    },
+
    "node_modules/base-x": {
+
      "version": "3.0.8",
+
      "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz",
+
      "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==",
+
      "dependencies": {
+
        "safe-buffer": "^5.0.1"
+
      }
+
    },
+
    "node_modules/base64-js": {
+
      "version": "1.5.1",
+
      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+
      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+
      "funding": [
+
        {
+
          "type": "github",
+
          "url": "https://github.com/sponsors/feross"
+
        },
+
        {
+
          "type": "patreon",
+
          "url": "https://www.patreon.com/feross"
+
        },
+
        {
+
          "type": "consulting",
+
          "url": "https://feross.org/support"
+
        }
+
      ]
+
    },
    "node_modules/bech32": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
@@ -1262,6 +1354,11 @@
        "node": ">=8"
      }
    },
+
    "node_modules/blakejs": {
+
      "version": "1.1.0",
+
      "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz",
+
      "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U="
+
    },
    "node_modules/bn.js": {
      "version": "4.12.0",
      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
@@ -1294,6 +1391,65 @@
      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
    },
+
    "node_modules/browserify-aes": {
+
      "version": "1.2.0",
+
      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+
      "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+
      "dependencies": {
+
        "buffer-xor": "^1.0.3",
+
        "cipher-base": "^1.0.0",
+
        "create-hash": "^1.1.0",
+
        "evp_bytestokey": "^1.0.3",
+
        "inherits": "^2.0.1",
+
        "safe-buffer": "^5.0.1"
+
      }
+
    },
+
    "node_modules/bs58": {
+
      "version": "4.0.1",
+
      "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
+
      "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=",
+
      "dependencies": {
+
        "base-x": "^3.0.2"
+
      }
+
    },
+
    "node_modules/bs58check": {
+
      "version": "2.1.2",
+
      "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
+
      "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
+
      "dependencies": {
+
        "bs58": "^4.0.0",
+
        "create-hash": "^1.1.0",
+
        "safe-buffer": "^5.1.2"
+
      }
+
    },
+
    "node_modules/buffer": {
+
      "version": "6.0.3",
+
      "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+
      "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+
      "funding": [
+
        {
+
          "type": "github",
+
          "url": "https://github.com/sponsors/feross"
+
        },
+
        {
+
          "type": "patreon",
+
          "url": "https://www.patreon.com/feross"
+
        },
+
        {
+
          "type": "consulting",
+
          "url": "https://feross.org/support"
+
        }
+
      ],
+
      "dependencies": {
+
        "base64-js": "^1.3.1",
+
        "ieee754": "^1.2.1"
+
      }
+
    },
+
    "node_modules/buffer-xor": {
+
      "version": "1.0.3",
+
      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+
      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+
    },
    "node_modules/callsites": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -1340,6 +1496,15 @@
        "fsevents": "~2.3.1"
      }
    },
+
    "node_modules/cipher-base": {
+
      "version": "1.0.4",
+
      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+
      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+
      "dependencies": {
+
        "inherits": "^2.0.1",
+
        "safe-buffer": "^5.0.1"
+
      }
+
    },
    "node_modules/color-convert": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -1379,6 +1544,31 @@
        "node": ">=0.8"
      }
    },
+
    "node_modules/create-hash": {
+
      "version": "1.2.0",
+
      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+
      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+
      "dependencies": {
+
        "cipher-base": "^1.0.1",
+
        "inherits": "^2.0.1",
+
        "md5.js": "^1.3.4",
+
        "ripemd160": "^2.0.1",
+
        "sha.js": "^2.4.0"
+
      }
+
    },
+
    "node_modules/create-hmac": {
+
      "version": "1.1.7",
+
      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+
      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+
      "dependencies": {
+
        "cipher-base": "^1.0.3",
+
        "create-hash": "^1.1.0",
+
        "inherits": "^2.0.1",
+
        "ripemd160": "^2.0.0",
+
        "safe-buffer": "^5.0.1",
+
        "sha.js": "^2.4.8"
+
      }
+
    },
    "node_modules/cross-spawn": {
      "version": "7.0.3",
      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -1734,6 +1924,49 @@
      "resolved": "https://registry.npmjs.org/ethereum-blockies/-/ethereum-blockies-0.1.1.tgz",
      "integrity": "sha1-h5/pWd7vSSp6krQ9w0ro3C7lkfw="
    },
+
    "node_modules/ethereum-cryptography": {
+
      "version": "0.1.3",
+
      "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
+
      "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==",
+
      "dependencies": {
+
        "@types/pbkdf2": "^3.0.0",
+
        "@types/secp256k1": "^4.0.1",
+
        "blakejs": "^1.1.0",
+
        "browserify-aes": "^1.2.0",
+
        "bs58check": "^2.1.2",
+
        "create-hash": "^1.2.0",
+
        "create-hmac": "^1.1.7",
+
        "hash.js": "^1.1.7",
+
        "keccak": "^3.0.0",
+
        "pbkdf2": "^3.0.17",
+
        "randombytes": "^2.1.0",
+
        "safe-buffer": "^5.1.2",
+
        "scrypt-js": "^3.0.0",
+
        "secp256k1": "^4.0.1",
+
        "setimmediate": "^1.0.5"
+
      }
+
    },
+
    "node_modules/ethereumjs-util": {
+
      "version": "7.0.10",
+
      "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz",
+
      "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==",
+
      "dependencies": {
+
        "@types/bn.js": "^5.1.0",
+
        "bn.js": "^5.1.2",
+
        "create-hash": "^1.1.2",
+
        "ethereum-cryptography": "^0.1.3",
+
        "ethjs-util": "0.1.6",
+
        "rlp": "^2.2.4"
+
      },
+
      "engines": {
+
        "node": ">=10.0.0"
+
      }
+
    },
+
    "node_modules/ethereumjs-util/node_modules/bn.js": {
+
      "version": "5.2.0",
+
      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
+
      "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
+
    },
    "node_modules/ethers": {
      "version": "5.3.0",
      "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.3.0.tgz",
@@ -1781,6 +2014,28 @@
        "@ethersproject/wordlists": "5.3.0"
      }
    },
+
    "node_modules/ethjs-util": {
+
      "version": "0.1.6",
+
      "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz",
+
      "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==",
+
      "dependencies": {
+
        "is-hex-prefixed": "1.0.0",
+
        "strip-hex-prefix": "1.0.0"
+
      },
+
      "engines": {
+
        "node": ">=6.5.0",
+
        "npm": ">=3"
+
      }
+
    },
+
    "node_modules/evp_bytestokey": {
+
      "version": "1.0.3",
+
      "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+
      "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+
      "dependencies": {
+
        "md5.js": "^1.3.4",
+
        "safe-buffer": "^5.1.1"
+
      }
+
    },
    "node_modules/fast-deep-equal": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -1868,6 +2123,25 @@
      "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
      "dev": true
    },
+
    "node_modules/follow-redirects": {
+
      "version": "1.14.1",
+
      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
+
      "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
+
      "funding": [
+
        {
+
          "type": "individual",
+
          "url": "https://github.com/sponsors/RubenVerborgh"
+
        }
+
      ],
+
      "engines": {
+
        "node": ">=4.0"
+
      },
+
      "peerDependenciesMeta": {
+
        "debug": {
+
          "optional": true
+
        }
+
      }
+
    },
    "node_modules/fs.realpath": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -1997,6 +2271,19 @@
        "node": ">=8"
      }
    },
+
    "node_modules/hash-base": {
+
      "version": "3.1.0",
+
      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+
      "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+
      "dependencies": {
+
        "inherits": "^2.0.4",
+
        "readable-stream": "^3.6.0",
+
        "safe-buffer": "^5.2.0"
+
      },
+
      "engines": {
+
        "node": ">=4"
+
      }
+
    },
    "node_modules/hash-sum": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
@@ -2022,6 +2309,25 @@
        "minimalistic-crypto-utils": "^1.0.1"
      }
    },
+
    "node_modules/ieee754": {
+
      "version": "1.2.1",
+
      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+
      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+
      "funding": [
+
        {
+
          "type": "github",
+
          "url": "https://github.com/sponsors/feross"
+
        },
+
        {
+
          "type": "patreon",
+
          "url": "https://www.patreon.com/feross"
+
        },
+
        {
+
          "type": "consulting",
+
          "url": "https://feross.org/support"
+
        }
+
      ]
+
    },
    "node_modules/ignore": {
      "version": "4.0.6",
      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@@ -2116,6 +2422,15 @@
        "node": ">=0.10.0"
      }
    },
+
    "node_modules/is-hex-prefixed": {
+
      "version": "1.0.0",
+
      "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz",
+
      "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=",
+
      "engines": {
+
        "node": ">=6.5.0",
+
        "npm": ">=3"
+
      }
+
    },
    "node_modules/is-number": {
      "version": "7.0.0",
      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -2167,6 +2482,19 @@
      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
      "dev": true
    },
+
    "node_modules/keccak": {
+
      "version": "3.0.1",
+
      "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz",
+
      "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==",
+
      "hasInstallScript": true,
+
      "dependencies": {
+
        "node-addon-api": "^2.0.0",
+
        "node-gyp-build": "^4.2.0"
+
      },
+
      "engines": {
+
        "node": ">=10.0.0"
+
      }
+
    },
    "node_modules/levn": {
      "version": "0.4.1",
      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -2235,6 +2563,16 @@
        "node": ">= 8.16.2"
      }
    },
+
    "node_modules/md5.js": {
+
      "version": "1.3.5",
+
      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+
      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+
      "dependencies": {
+
        "hash-base": "^3.0.0",
+
        "inherits": "^2.0.1",
+
        "safe-buffer": "^5.1.2"
+
      }
+
    },
    "node_modules/merge2": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -2352,6 +2690,21 @@
        "tslib": "^2.0.3"
      }
    },
+
    "node_modules/node-addon-api": {
+
      "version": "2.0.2",
+
      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
+
      "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA=="
+
    },
+
    "node_modules/node-gyp-build": {
+
      "version": "4.2.3",
+
      "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
+
      "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==",
+
      "bin": {
+
        "node-gyp-build": "bin.js",
+
        "node-gyp-build-optional": "optional.js",
+
        "node-gyp-build-test": "build-test.js"
+
      }
+
    },
    "node_modules/normalize-path": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -2441,6 +2794,21 @@
        "node": ">=8"
      }
    },
+
    "node_modules/pbkdf2": {
+
      "version": "3.1.2",
+
      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
+
      "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
+
      "dependencies": {
+
        "create-hash": "^1.1.2",
+
        "create-hmac": "^1.1.4",
+
        "ripemd160": "^2.0.1",
+
        "safe-buffer": "^5.0.1",
+
        "sha.js": "^2.4.8"
+
      },
+
      "engines": {
+
        "node": ">=0.12"
+
      }
+
    },
    "node_modules/picomatch": {
      "version": "2.2.3",
      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
@@ -2518,6 +2886,27 @@
        }
      ]
    },
+
    "node_modules/randombytes": {
+
      "version": "2.1.0",
+
      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+
      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+
      "dependencies": {
+
        "safe-buffer": "^5.1.0"
+
      }
+
    },
+
    "node_modules/readable-stream": {
+
      "version": "3.6.0",
+
      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+
      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+
      "dependencies": {
+
        "inherits": "^2.0.3",
+
        "string_decoder": "^1.1.1",
+
        "util-deprecate": "^1.0.1"
+
      },
+
      "engines": {
+
        "node": ">= 6"
+
      }
+
    },
    "node_modules/readdirp": {
      "version": "3.5.0",
      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
@@ -2604,6 +2993,26 @@
        "url": "https://github.com/sponsors/isaacs"
      }
    },
+
    "node_modules/ripemd160": {
+
      "version": "2.0.2",
+
      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+
      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+
      "dependencies": {
+
        "hash-base": "^3.0.0",
+
        "inherits": "^2.0.1"
+
      }
+
    },
+
    "node_modules/rlp": {
+
      "version": "2.2.6",
+
      "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz",
+
      "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==",
+
      "dependencies": {
+
        "bn.js": "^4.11.1"
+
      },
+
      "bin": {
+
        "rlp": "bin/rlp"
+
      }
+
    },
    "node_modules/rollup": {
      "version": "2.47.0",
      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.47.0.tgz",
@@ -2642,11 +3051,44 @@
        "queue-microtask": "^1.2.2"
      }
    },
+
    "node_modules/safe-buffer": {
+
      "version": "5.2.1",
+
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+
      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+
      "funding": [
+
        {
+
          "type": "github",
+
          "url": "https://github.com/sponsors/feross"
+
        },
+
        {
+
          "type": "patreon",
+
          "url": "https://www.patreon.com/feross"
+
        },
+
        {
+
          "type": "consulting",
+
          "url": "https://feross.org/support"
+
        }
+
      ]
+
    },
    "node_modules/scrypt-js": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz",
      "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA=="
    },
+
    "node_modules/secp256k1": {
+
      "version": "4.0.2",
+
      "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz",
+
      "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==",
+
      "hasInstallScript": true,
+
      "dependencies": {
+
        "elliptic": "^6.5.2",
+
        "node-addon-api": "^2.0.0",
+
        "node-gyp-build": "^4.2.0"
+
      },
+
      "engines": {
+
        "node": ">=10.0.0"
+
      }
+
    },
    "node_modules/semver": {
      "version": "7.3.5",
      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@@ -2662,6 +3104,23 @@
        "node": ">=10"
      }
    },
+
    "node_modules/setimmediate": {
+
      "version": "1.0.5",
+
      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+
      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+
    },
+
    "node_modules/sha.js": {
+
      "version": "2.4.11",
+
      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+
      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+
      "dependencies": {
+
        "inherits": "^2.0.1",
+
        "safe-buffer": "^5.0.1"
+
      },
+
      "bin": {
+
        "sha.js": "bin.js"
+
      }
+
    },
    "node_modules/shebang-command": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -2742,6 +3201,26 @@
      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
      "dev": true
    },
+
    "node_modules/string_decoder": {
+
      "version": "1.3.0",
+
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+
      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+
      "dependencies": {
+
        "safe-buffer": "~5.2.0"
+
      }
+
    },
+
    "node_modules/strip-hex-prefix": {
+
      "version": "1.0.0",
+
      "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz",
+
      "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=",
+
      "dependencies": {
+
        "is-hex-prefixed": "1.0.0"
+
      },
+
      "engines": {
+
        "node": ">=6.5.0",
+
        "npm": ">=3"
+
      }
+
    },
    "node_modules/strip-indent": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
@@ -3074,6 +3553,11 @@
        "punycode": "^2.1.0"
      }
    },
+
    "node_modules/util-deprecate": {
+
      "version": "1.0.2",
+
      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+
      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+
    },
    "node_modules/v8-compile-cache": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
@@ -3658,6 +4142,29 @@
        "@ethersproject/strings": "^5.3.0"
      }
    },
+
    "@gnosis.pm/safe-core-sdk": {
+
      "version": "0.2.0",
+
      "resolved": "https://registry.npmjs.org/@gnosis.pm/safe-core-sdk/-/safe-core-sdk-0.2.0.tgz",
+
      "integrity": "sha512-HofU9KvbdMyoblvVyjTAEGNjdte4CamIfbZ5VgmAZhm2j8DwVJ6kqqRjGVar36eOv3sfozuJmnZwkPMM9BaV8Q==",
+
      "requires": {
+
        "@gnosis.pm/safe-core-sdk-types": "^0.1.1",
+
        "ethereumjs-util": "^7.0.10"
+
      }
+
    },
+
    "@gnosis.pm/safe-core-sdk-types": {
+
      "version": "0.1.1",
+
      "resolved": "https://registry.npmjs.org/@gnosis.pm/safe-core-sdk-types/-/safe-core-sdk-types-0.1.1.tgz",
+
      "integrity": "sha512-PghXGDaI5Foq37nZGmI90U2OKMeGtxh5KqkDqou9aFHwGVa/nf9HRQPxG9/XUzcyfe9OlKttDlJnR3XnC3dSDw=="
+
    },
+
    "@gnosis.pm/safe-service-client": {
+
      "version": "0.1.0-alpha.0",
+
      "resolved": "https://registry.npmjs.org/@gnosis.pm/safe-service-client/-/safe-service-client-0.1.0-alpha.0.tgz",
+
      "integrity": "sha512-Ld8B7VMAjjWMrywa+SNrLw+w4qJrvd6OEeLUkUTfFK6yDW9ybbfy6QO6bUMgOP4WhgUdRnTVpm/526DcddkifA==",
+
      "requires": {
+
        "@gnosis.pm/safe-core-sdk-types": "^0.1.0",
+
        "axios": "^0.21.1"
+
      }
+
    },
    "@multiformats/base-x": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/@multiformats/base-x/-/base-x-4.0.1.tgz",
@@ -3707,6 +4214,11 @@
        }
      }
    },
+
    "@stardazed/streams": {
+
      "version": "3.1.0",
+
      "resolved": "https://registry.npmjs.org/@stardazed/streams/-/streams-3.1.0.tgz",
+
      "integrity": "sha512-+fNbzyPb65oknwBgMjJrfs7dPXIJTDgnrFQcLI9+tpYTvHgrxwlqMm8geV4NA640qp+udIenWQDLU+hsB06Vcw=="
+
    },
    "@sveltejs/vite-plugin-svelte": {
      "version": "1.0.0-next.10",
      "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.10.tgz",
@@ -3744,6 +4256,14 @@
      "integrity": "sha512-EBrpH2iXXfaf/9z81koiDYkp2mlwW2XzFcAqn6qh7VKyP8zBvHHAQzNhY+W9vH5arAjmGAm5g8ElWq6YmXm3ig==",
      "dev": true
    },
+
    "@types/bn.js": {
+
      "version": "5.1.0",
+
      "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz",
+
      "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==",
+
      "requires": {
+
        "@types/node": "*"
+
      }
+
    },
    "@types/json-schema": {
      "version": "7.0.7",
      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
@@ -3760,6 +4280,14 @@
      "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz",
      "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww=="
    },
+
    "@types/pbkdf2": {
+
      "version": "3.1.0",
+
      "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz",
+
      "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==",
+
      "requires": {
+
        "@types/node": "*"
+
      }
+
    },
    "@types/pug": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.4.tgz",
@@ -3773,6 +4301,14 @@
        "@types/node": "*"
      }
    },
+
    "@types/secp256k1": {
+
      "version": "4.0.2",
+
      "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.2.tgz",
+
      "integrity": "sha512-QMg+9v0bbNJ2peLuHRWxzmy0HRJIG6gFZNhaRSp7S3ggSbCCxiqQB2/ybvhXyhHOCequpNkrx7OavNhrWOsW0A==",
+
      "requires": {
+
        "@types/node": "*"
+
      }
+
    },
    "@typescript-eslint/eslint-plugin": {
      "version": "4.26.1",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.26.1.tgz",
@@ -3943,12 +4479,33 @@
      "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
      "dev": true
    },
+
    "axios": {
+
      "version": "0.21.1",
+
      "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
+
      "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
+
      "requires": {
+
        "follow-redirects": "^1.10.0"
+
      }
+
    },
    "balanced-match": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
      "dev": true
    },
+
    "base-x": {
+
      "version": "3.0.8",
+
      "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz",
+
      "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==",
+
      "requires": {
+
        "safe-buffer": "^5.0.1"
+
      }
+
    },
+
    "base64-js": {
+
      "version": "1.5.1",
+
      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+
      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+
    },
    "bech32": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
@@ -3960,6 +4517,11 @@
      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
      "dev": true
    },
+
    "blakejs": {
+
      "version": "1.1.0",
+
      "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz",
+
      "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U="
+
    },
    "bn.js": {
      "version": "4.12.0",
      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
@@ -3989,6 +4551,51 @@
      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
    },
+
    "browserify-aes": {
+
      "version": "1.2.0",
+
      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+
      "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+
      "requires": {
+
        "buffer-xor": "^1.0.3",
+
        "cipher-base": "^1.0.0",
+
        "create-hash": "^1.1.0",
+
        "evp_bytestokey": "^1.0.3",
+
        "inherits": "^2.0.1",
+
        "safe-buffer": "^5.0.1"
+
      }
+
    },
+
    "bs58": {
+
      "version": "4.0.1",
+
      "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
+
      "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=",
+
      "requires": {
+
        "base-x": "^3.0.2"
+
      }
+
    },
+
    "bs58check": {
+
      "version": "2.1.2",
+
      "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
+
      "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
+
      "requires": {
+
        "bs58": "^4.0.0",
+
        "create-hash": "^1.1.0",
+
        "safe-buffer": "^5.1.2"
+
      }
+
    },
+
    "buffer": {
+
      "version": "6.0.3",
+
      "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+
      "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+
      "requires": {
+
        "base64-js": "^1.3.1",
+
        "ieee754": "^1.2.1"
+
      }
+
    },
+
    "buffer-xor": {
+
      "version": "1.0.3",
+
      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+
      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+
    },
    "callsites": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -4021,6 +4628,15 @@
        "readdirp": "~3.5.0"
      }
    },
+
    "cipher-base": {
+
      "version": "1.0.4",
+
      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+
      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+
      "requires": {
+
        "inherits": "^2.0.1",
+
        "safe-buffer": "^5.0.1"
+
      }
+
    },
    "color-convert": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -4054,6 +4670,31 @@
      "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
      "dev": true
    },
+
    "create-hash": {
+
      "version": "1.2.0",
+
      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+
      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+
      "requires": {
+
        "cipher-base": "^1.0.1",
+
        "inherits": "^2.0.1",
+
        "md5.js": "^1.3.4",
+
        "ripemd160": "^2.0.1",
+
        "sha.js": "^2.4.0"
+
      }
+
    },
+
    "create-hmac": {
+
      "version": "1.1.7",
+
      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+
      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+
      "requires": {
+
        "cipher-base": "^1.0.3",
+
        "create-hash": "^1.1.0",
+
        "inherits": "^2.0.1",
+
        "ripemd160": "^2.0.0",
+
        "safe-buffer": "^5.0.1",
+
        "sha.js": "^2.4.8"
+
      }
+
    },
    "cross-spawn": {
      "version": "7.0.3",
      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -4323,6 +4964,48 @@
      "resolved": "https://registry.npmjs.org/ethereum-blockies/-/ethereum-blockies-0.1.1.tgz",
      "integrity": "sha1-h5/pWd7vSSp6krQ9w0ro3C7lkfw="
    },
+
    "ethereum-cryptography": {
+
      "version": "0.1.3",
+
      "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
+
      "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==",
+
      "requires": {
+
        "@types/pbkdf2": "^3.0.0",
+
        "@types/secp256k1": "^4.0.1",
+
        "blakejs": "^1.1.0",
+
        "browserify-aes": "^1.2.0",
+
        "bs58check": "^2.1.2",
+
        "create-hash": "^1.2.0",
+
        "create-hmac": "^1.1.7",
+
        "hash.js": "^1.1.7",
+
        "keccak": "^3.0.0",
+
        "pbkdf2": "^3.0.17",
+
        "randombytes": "^2.1.0",
+
        "safe-buffer": "^5.1.2",
+
        "scrypt-js": "^3.0.0",
+
        "secp256k1": "^4.0.1",
+
        "setimmediate": "^1.0.5"
+
      }
+
    },
+
    "ethereumjs-util": {
+
      "version": "7.0.10",
+
      "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz",
+
      "integrity": "sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==",
+
      "requires": {
+
        "@types/bn.js": "^5.1.0",
+
        "bn.js": "^5.1.2",
+
        "create-hash": "^1.1.2",
+
        "ethereum-cryptography": "^0.1.3",
+
        "ethjs-util": "0.1.6",
+
        "rlp": "^2.2.4"
+
      },
+
      "dependencies": {
+
        "bn.js": {
+
          "version": "5.2.0",
+
          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
+
          "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
+
        }
+
      }
+
    },
    "ethers": {
      "version": "5.3.0",
      "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.3.0.tgz",
@@ -4360,6 +5043,24 @@
        "@ethersproject/wordlists": "5.3.0"
      }
    },
+
    "ethjs-util": {
+
      "version": "0.1.6",
+
      "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz",
+
      "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==",
+
      "requires": {
+
        "is-hex-prefixed": "1.0.0",
+
        "strip-hex-prefix": "1.0.0"
+
      }
+
    },
+
    "evp_bytestokey": {
+
      "version": "1.0.3",
+
      "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+
      "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+
      "requires": {
+
        "md5.js": "^1.3.4",
+
        "safe-buffer": "^5.1.1"
+
      }
+
    },
    "fast-deep-equal": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -4435,6 +5136,11 @@
      "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==",
      "dev": true
    },
+
    "follow-redirects": {
+
      "version": "1.14.1",
+
      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
+
      "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
+
    },
    "fs.realpath": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -4529,6 +5235,16 @@
      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
      "dev": true
    },
+
    "hash-base": {
+
      "version": "3.1.0",
+
      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+
      "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+
      "requires": {
+
        "inherits": "^2.0.4",
+
        "readable-stream": "^3.6.0",
+
        "safe-buffer": "^5.2.0"
+
      }
+
    },
    "hash-sum": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
@@ -4554,6 +5270,11 @@
        "minimalistic-crypto-utils": "^1.0.1"
      }
    },
+
    "ieee754": {
+
      "version": "1.2.1",
+
      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+
      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
+
    },
    "ignore": {
      "version": "4.0.6",
      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@@ -4624,6 +5345,11 @@
        "is-extglob": "^2.1.1"
      }
    },
+
    "is-hex-prefixed": {
+
      "version": "1.0.0",
+
      "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz",
+
      "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ="
+
    },
    "is-number": {
      "version": "7.0.0",
      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -4669,6 +5395,15 @@
      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
      "dev": true
    },
+
    "keccak": {
+
      "version": "3.0.1",
+
      "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz",
+
      "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==",
+
      "requires": {
+
        "node-addon-api": "^2.0.0",
+
        "node-gyp-build": "^4.2.0"
+
      }
+
    },
    "levn": {
      "version": "0.4.1",
      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -4725,6 +5460,16 @@
      "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.7.tgz",
      "integrity": "sha512-BJXxkuIfJchcXOJWTT2DOL+yFWifFv2yGYOUzvXg8Qz610QKw+sHCvTMYwA+qWGhlA2uivBezChZ/pBy1tWdkQ=="
    },
+
    "md5.js": {
+
      "version": "1.3.5",
+
      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+
      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+
      "requires": {
+
        "hash-base": "^3.0.0",
+
        "inherits": "^2.0.1",
+
        "safe-buffer": "^5.1.2"
+
      }
+
    },
    "merge2": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -4816,6 +5561,16 @@
        "tslib": "^2.0.3"
      }
    },
+
    "node-addon-api": {
+
      "version": "2.0.2",
+
      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
+
      "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA=="
+
    },
+
    "node-gyp-build": {
+
      "version": "4.2.3",
+
      "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
+
      "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg=="
+
    },
    "normalize-path": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -4887,6 +5642,18 @@
      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
      "dev": true
    },
+
    "pbkdf2": {
+
      "version": "3.1.2",
+
      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
+
      "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
+
      "requires": {
+
        "create-hash": "^1.1.2",
+
        "create-hmac": "^1.1.4",
+
        "ripemd160": "^2.0.1",
+
        "safe-buffer": "^5.0.1",
+
        "sha.js": "^2.4.8"
+
      }
+
    },
    "picomatch": {
      "version": "2.2.3",
      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
@@ -4928,6 +5695,24 @@
      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
      "dev": true
    },
+
    "randombytes": {
+
      "version": "2.1.0",
+
      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+
      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+
      "requires": {
+
        "safe-buffer": "^5.1.0"
+
      }
+
    },
+
    "readable-stream": {
+
      "version": "3.6.0",
+
      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+
      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+
      "requires": {
+
        "inherits": "^2.0.3",
+
        "string_decoder": "^1.1.1",
+
        "util-deprecate": "^1.0.1"
+
      }
+
    },
    "readdirp": {
      "version": "3.5.0",
      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
@@ -4986,6 +5771,23 @@
        "glob": "^7.1.3"
      }
    },
+
    "ripemd160": {
+
      "version": "2.0.2",
+
      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+
      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+
      "requires": {
+
        "hash-base": "^3.0.0",
+
        "inherits": "^2.0.1"
+
      }
+
    },
+
    "rlp": {
+
      "version": "2.2.6",
+
      "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz",
+
      "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==",
+
      "requires": {
+
        "bn.js": "^4.11.1"
+
      }
+
    },
    "rollup": {
      "version": "2.47.0",
      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.47.0.tgz",
@@ -5004,11 +5806,26 @@
        "queue-microtask": "^1.2.2"
      }
    },
+
    "safe-buffer": {
+
      "version": "5.2.1",
+
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+
      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+
    },
    "scrypt-js": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz",
      "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA=="
    },
+
    "secp256k1": {
+
      "version": "4.0.2",
+
      "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz",
+
      "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==",
+
      "requires": {
+
        "elliptic": "^6.5.2",
+
        "node-addon-api": "^2.0.0",
+
        "node-gyp-build": "^4.2.0"
+
      }
+
    },
    "semver": {
      "version": "7.3.5",
      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@@ -5018,6 +5835,20 @@
        "lru-cache": "^6.0.0"
      }
    },
+
    "setimmediate": {
+
      "version": "1.0.5",
+
      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+
      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+
    },
+
    "sha.js": {
+
      "version": "2.4.11",
+
      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+
      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+
      "requires": {
+
        "inherits": "^2.0.1",
+
        "safe-buffer": "^5.0.1"
+
      }
+
    },
    "shebang-command": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -5076,6 +5907,22 @@
      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
      "dev": true
    },
+
    "string_decoder": {
+
      "version": "1.3.0",
+
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+
      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+
      "requires": {
+
        "safe-buffer": "~5.2.0"
+
      }
+
    },
+
    "strip-hex-prefix": {
+
      "version": "1.0.0",
+
      "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz",
+
      "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=",
+
      "requires": {
+
        "is-hex-prefixed": "1.0.0"
+
      }
+
    },
    "strip-indent": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
@@ -5288,6 +6135,11 @@
        "punycode": "^2.1.0"
      }
    },
+
    "util-deprecate": {
+
      "version": "1.0.2",
+
      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+
      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+
    },
    "v8-compile-cache": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
modified package.json
@@ -21,7 +21,12 @@
    "vite-plugin-rewrite-all": "^0.1.2"
  },
  "dependencies": {
+
    "@gnosis.pm/safe-core-sdk": "^0.2.0",
+
    "@gnosis.pm/safe-core-sdk-types": "^0.1.1",
+
    "@gnosis.pm/safe-service-client": "^0.1.0-alpha.0",
+
    "@stardazed/streams": "^3.1.0",
    "@types/marked": "^2.0.3",
+
    "buffer": "^6.0.3",
    "ethereum-blockies": "^0.1.1",
    "ethers": "^5.0.31",
    "marked": "^2.0.7",
modified src/Address.svelte
@@ -37,7 +37,7 @@

<style>
  .address {
-
    display: flex;
+
    display: inline-flex;
    align-items: center;
    height: 100%;
  }
@@ -53,6 +53,7 @@
  .loading {
    margin-left: 1rem;
    width: 4rem;
+
    height: 1.5rem;
  }
</style>

modified src/Error.svelte
@@ -11,6 +11,7 @@
  export let message = "";
  export let floating = false;
  export let subtle = false;
+
  export let action = floating ? "Close" : "Back";

  let body = message || (error && error.message) || "";
</script>
@@ -32,7 +33,7 @@

  <span slot="actions">
    <button on:click={() => dispatch('close')}>
-
      Back
+
      {action}
    </button>
  </span>
</Modal>
modified src/Loading.svelte
@@ -8,6 +8,12 @@
</script>

<style>
+
  .container {
+
    display: flex;
+
    align-items: center;
+
    height: 100%;
+
  }
+

  .spinner {
    margin: auto 0;
    width: 70px;
@@ -106,10 +112,12 @@
  }
</style>

-
<div class="spinner" class:fade-in={fadeIn} class:small class:center class:margins class:condensed>
-
  <div class="bounce1" style="background-color: var(--color-{color})"></div>
-
  {#if !condensed}
-
    <div class="bounce2" style="background-color: var(--color-{color})"></div>
-
    <div class="bounce3" style="background-color: var(--color-{color})"></div>
-
  {/if}
+
<div class="container">
+
  <div class="spinner" class:fade-in={fadeIn} class:small class:center class:margins class:condensed>
+
    <div class="bounce1" style="background-color: var(--color-{color})"></div>
+
    {#if !condensed}
+
      <div class="bounce2" style="background-color: var(--color-{color})"></div>
+
      <div class="bounce3" style="background-color: var(--color-{color})"></div>
+
    {/if}
+
  </div>
</div>
modified src/base/orgs/Org.ts
@@ -1,6 +1,8 @@
import * as ethers from 'ethers';
import type { TransactionResponse } from '@ethersproject/providers';
import type { ContractReceipt } from '@ethersproject/contracts';
+
import { OperationType } from "@gnosis.pm/safe-core-sdk-types";
+

import { assert } from '@app/error';
import * as utils from '@app/utils';
import type { Config } from '@app/config';
@@ -74,6 +76,36 @@ export class Org {
      { gasLimit: 200_000 });
  }

+
  async setNameMultisig(name: string, config: Config): Promise<void> {
+
    assert(config.signer);
+
    assert(config.safe.client);
+

+
    const safeAddress = ethers.utils.getAddress(this.owner);
+
    const orgAddress = ethers.utils.getAddress(this.address);
+
    const org = new ethers.Contract(
+
      this.address,
+
      config.abi.org,
+
      config.signer
+
    );
+
    const unsignedTx = await org.populateTransaction.setName(
+
      name,
+
      config.provider.network.ensAddress,
+
    );
+

+
    const txData = unsignedTx.data;
+
    if (! txData) {
+
      throw new Error("Org::setNameMultisig: Could not generate transaction for `setName` call");
+
    }
+

+
    const safeTx = {
+
      to: orgAddress,
+
      value: ethers.constants.Zero.toString(),
+
      data: txData,
+
      operation: OperationType.Call,
+
    };
+
    await utils.proposeSafeTransaction(safeTx, safeAddress, config);
+
  }
+

  async setOwner(address: string, config: Config): Promise<TransactionResponse> {
    assert(config.signer);

@@ -93,6 +125,11 @@ export class Org {
    return [];
  }

+
  async isMember(address: string, config: Config): Promise<boolean> {
+
    const members = await this.getMembers(config);
+
    return members.includes(ethers.utils.getAddress(address));
+
  }
+

  async getProjects(config: Config): Promise<Array<Project>> {
    const result = await utils.querySubgraph(
      config.orgs.subgraph, GetProjects, { org: this.address }
modified src/base/orgs/View.svelte
@@ -45,8 +45,14 @@
  };

  $: label = name && parseEnsLabel(name, config);
-
  $: isOwner = (org: Org): boolean => {
-
    return $session ? utils.isAddressEqual(org.owner, $session.address) : false;
+
  $: isAuthorized = async (org: Org): Promise<boolean> => {
+
    if ($session) {
+
      if (utils.isAddressEqual(org.owner, $session.address)) {
+
        return true;
+
      }
+
      return await org.isMember($session.address, config);
+
    }
+
    return false;
  };
</script>

@@ -171,17 +177,21 @@
        <div class="label">Owner</div>
        <div><Address resolve {config} address={org.owner} /></div>
        <div>
-
          {#if isOwner(org)}
-
            <button class="tiny secondary" on:click={transferOwnership}>
-
              Transfer
-
            </button>
-
          {/if}
+
          {#await isAuthorized(org)}
+
            <!-- Loading -->
+
          {:then authorized}
+
            {#if authorized}
+
              <button class="tiny secondary" on:click={transferOwnership}>
+
                Transfer
+
              </button>
+
            {/if}
+
          {/await}
        </div>
        <!-- Name -->
        <div class="label">Name</div>
        <div>
          {#await org.lookupAddress(config)}
-
            <Loading small />
+
            <div class="loading"><Loading small /></div>
          {:then name}
            {#if name}
              <Link to={`/registrations/${label}`}>{name}</Link>
@@ -191,11 +201,15 @@
          {/await}
        </div>
        <div>
-
          {#if isOwner(org)}
-
            <button class="tiny secondary" on:click={setName}>
-
              Set
-
            </button>
-
          {/if}
+
          {#await isAuthorized(org)}
+
            <!-- Loading -->
+
          {:then authorized}
+
            {#if authorized}
+
              <button class="tiny secondary" on:click={setName}>
+
                Set
+
              </button>
+
            {/if}
+
          {/await}
        </div>
      </div>

modified src/config.json
@@ -15,7 +15,7 @@
      "contractHash": "0x5c34bb0755876de98e801805e6685456eea739ad0abba1cc450a7ee0f2a70b74"
    },
    "safe": {
-
      "api": "https://safe-transaction.gnosis.io/api/v1",
+
      "api": "https://safe-transaction.gnosis.io",
      "subgraph": null,
      "viewer": "https://gnosis-safe.io/app/#/safes"
    },
@@ -59,7 +59,7 @@
      "contractHash": "0x5c34bb0755876de98e801805e6685456eea739ad0abba1cc450a7ee0f2a70b74"
    },
    "safe": {
-
      "api": "https://safe-transaction.rinkeby.gnosis.io/api/v1",
+
      "api": "https://safe-transaction.rinkeby.gnosis.io",
      "subgraph": "https://api.thegraph.com/subgraphs/name/radicle-dev/gnosis-safe-rinkeby",
      "viewer": "https://rinkeby.gnosis-safe.io/app/#/safes"
    },
modified src/config.ts
@@ -1,5 +1,6 @@
import { ethers } from "ethers";
import type { TypedDataSigner } from '@ethersproject/abstract-signer';
+
import SafeServiceClient from "@gnosis.pm/safe-service-client";
import config from "@app/config.json";

declare global {
@@ -7,7 +8,6 @@ declare global {
    ethereum: any;
    registrarState: any;
  }
-

}

export class Config {
@@ -19,7 +19,12 @@ export class Config {
  gasLimits: { createOrg: number };
  provider: ethers.providers.JsonRpcProvider;
  signer: ethers.Signer & TypedDataSigner | null;
-
  safe: { api: string | null; subgraph: string; viewer: string | null };
+
  safe: {
+
    api?: string;
+
    client?: SafeServiceClient;
+
    subgraph: string;
+
    viewer: string | null;
+
  };
  abi: { [contract: string]: string[] };
  seed: { api?: string };
  tokens: string[];
@@ -44,6 +49,9 @@ export class Config {
    this.orgFactory = cfg.orgFactory;
    this.orgs = cfg.orgs;
    this.safe = cfg.safe;
+
    this.safe.client = this.safe.api
+
      ? new SafeServiceClient(this.safe.api)
+
      : undefined;
    this.provider = provider;
    this.signer = signer;
    this.gasLimits = gasLimits;
modified src/ens/SetName.svelte
@@ -7,6 +7,8 @@
  import type { Org } from '@app/base/orgs/Org';
  import Loading from '@app/Loading.svelte';
  import Error from '@app/Error.svelte';
+
  import Address from '@app/Address.svelte';
+
  import * as utils from '@app/utils';

  const dispatch = createEventDispatcher();

@@ -16,16 +18,23 @@
  enum State {
    Idle,
    Checking,
+

+
    // Single-sig states.
    Signing,
    Pending,
    Success,
+

+
    // Multi-sig states.
+
    Proposing,
+
    Proposed,
+

    Failed,
+
    Mismatch,
  }

  let name = "";
  let state = State.Idle;
  let error: string | null = null;
-
  let mismatchError = false; // Set if the name entered does not resolve to the address.

  const onSubmit = async () => {
    state = State.Checking;
@@ -34,20 +43,25 @@
    let resolved = await config.provider.resolveName(domain);

    if (resolved && isAddressEqual(resolved, org.address)) {
-
      state = State.Signing;
      try {
-
        let tx = await org.setName(domain, config);
-
        state = State.Pending;
-
        await tx.wait();
-
        state = State.Success;
+
        if (utils.isSafe(org.owner, config)) {
+
          state = State.Proposing;
+
          await org.setNameMultisig(domain, config);
+
          state = State.Proposed;
+
        } else {
+
          state = State.Signing;
+
          let tx = await org.setName(domain, config);
+
          state = State.Pending;
+
          await tx.wait();
+
          state = State.Success;
+
        }
      } catch (e) {
        console.error(e);
        state = State.Failed;
        error = e.message;
      }
    } else {
-
      state = State.Idle;
-
      mismatchError = true;
+
      state = State.Mismatch;
    }
  };
</script>
@@ -69,31 +83,31 @@
      </button>
    </div>
  </Modal>
-
{:else if mismatchError}
-
  <Modal floating error>
+
{:else if state === State.Proposed}
+
  <Modal floating>
    <div slot="title">
-
      ðŸ‘ŧ
+
      ðŸŠī
    </div>

-
    <div slot="body">
-
      <div class="error">
-
        The name <strong>{name}.{config.registrar.domain}</strong> does not
-
        resolve to <strong>{formatAddress(org.address)}</strong>. Please update
-
        The ENS record for {name}.{config.registrar.domain} to
-
        point to the correct address and try again.
-
      </div>
+
    <div slot="subtitle">
+
      <p>The transaction to set the ENS name for <strong>{formatAddress(org.address)}</strong>
+
      to <strong>{name}.{config.registrar.domain}</strong> was proposed to:</p>
+
      <p><Address address={org.owner} {config} compact /></p>
    </div>

    <div slot="actions">
-
      <button class="secondary" on:click={() => mismatchError = false}>
-
        Back
-
      </button>
-

-
      <button class="text" on:click={() => dispatch('close')}>
-
        Cancel
+
      <button class="small" on:click={() => dispatch('close')}>
+
        Done
      </button>
    </div>
  </Modal>
+
{:else if state === State.Mismatch}
+
  <Error floating title="🖊ïļ" action="Okay" on:close>
+
    The name <strong>{name}.{config.registrar.domain}</strong> does not
+
    resolve to <strong>{formatAddress(org.address)}</strong>. Please update
+
    The ENS record for {name}.{config.registrar.domain} to
+
    point to the correct address and try again.
+
  </Error>
{:else if state === State.Failed && error}
  <Error floating title="Transaction failed" message={error} on:close />
{:else}
@@ -107,6 +121,10 @@
        Please confirm the transaction in your wallet.
      {:else if state == State.Pending}
        Transaction is being processed by the network...
+
      {:else if state == State.Proposing}
+
        Proposal is being submitted to the safe
+
        <strong>{formatAddress(org.owner)}</strong>,
+
        please sign the transaction in your wallet.
      {:else}
        Set an ENS name for <strong>{formatAddress(org.address)}</strong>
      {/if}
@@ -114,7 +132,7 @@

    <div slot="body">
      {#if state === State.Idle || state === State.Checking}
-
        <DomainInput root={config.registrar.domain} on:input={() => mismatchError = false}
+
        <DomainInput root={config.registrar.domain}
          autofocus disabled={state !== State.Idle} bind:value={name} />
      {:else}
        <Loading small center />
added src/polyfills/stream.ts
@@ -0,0 +1,7 @@
+
// This shim is used as a stand-in for the node "stream" library, used by
+
// the "keccack" package depended on by @gnosis.pm/safe-core-sdk.
+
import * as streams from '@stardazed/streams';
+

+
// "Transform" is the old name for "TransformStream".
+
export const Transform = streams.TransformStream;
+
export default streams;
modified src/utils.ts
@@ -2,7 +2,9 @@ import { ethers } from "ethers";
import type { BigNumber } from "ethers";
import multibase from 'multibase';
import multihashes from 'multihashes';
+
import EthersSafe from "@gnosis.pm/safe-core-sdk";
import type { Config } from '@app/config';
+
import { assert } from '@app/error';

export enum AddressType {
  Contract,
@@ -17,6 +19,13 @@ export interface Safe {
  threshold: number;
}

+
export interface SafeTransaction {
+
    to: string;
+
    value: string;
+
    data: string;
+
    operation: number;
+
}
+

export function isAddressEqual(left: string, right: string): boolean {
  return left.toLowerCase() === right.toLowerCase();
}
@@ -178,7 +187,7 @@ export async function isSafe(address: string, config: Config): Promise<boolean>
  if (! config.safe.api) return false;

  const addr = ethers.utils.getAddress(address);
-
  const response = await fetch(`${config.safe.api}/safes/${addr}`, { method: 'HEAD' });
+
  const response = await fetch(`${config.safe.api}/api/v1/safes/${addr}`, { method: 'HEAD' });

  return response.ok;
}
@@ -188,7 +197,7 @@ export async function getSafe(address: string, config: Config): Promise<Safe | n
  if (! config.safe.api) return null;

  const addr = ethers.utils.getAddress(address);
-
  const response = await fetch(`${config.safe.api}/safes/${addr}`, {
+
  const response = await fetch(`${config.safe.api}/api/v1/safes/${addr}`, {
    method: 'GET',
    headers: {
      'Accept': 'application/json',
@@ -221,3 +230,34 @@ export async function getTokens(address: string, config: Config):
export function isMarkdownPath(path: string): boolean {
  return /\.(md|mkd|markdown)$/i.test(path);
}
+

+
// Propose a Gnosis Safe multi-sig transaction.
+
export async function proposeSafeTransaction(
+
  safeTx: SafeTransaction,
+
  safeAddress: string,
+
  config: Config
+
): Promise<void> {
+
  assert(config.signer);
+
  assert(config.safe.client);
+

+
  const safeSdk = await EthersSafe.create({
+
    ethers, safeAddress, providerOrSigner: config.signer,
+
  });
+
  const estimation = await config.safe.client.estimateSafeTransaction(
+
    safeAddress,
+
    safeTx
+
  );
+
  const transaction = await safeSdk.createTransaction({
+
    ...safeTx,
+
    safeTxGas: Number(estimation.safeTxGas),
+
  });
+
  const safeTxHash = await safeSdk.getTransactionHash(transaction);
+
  const signature = await safeSdk.signTransactionHash(safeTxHash);
+

+
  await config.safe.client.proposeTransaction(
+
    safeAddress,
+
    transaction.data,
+
    safeTxHash,
+
    signature
+
  );
+
}
modified vite.config.ts
@@ -11,6 +11,8 @@ const config: UserConfig = {
  resolve: {
    alias: {
      "@app": path.resolve("./src"),
+
      // Polyfill for Node.js "stream" library.
+
      "stream": path.resolve("./src/polyfills/stream.ts"),
    },
  },
  build: {