I want to use Gnosis Safe's Multisig wallet both from a web app(Next.js) and a mobile app(React Native). For this, using Safe Core SDK on the backend and building APIs using it seems a good approach. So, after doing some research I found this code example which shows the implementation of OpenSea SDK with Node.js. That example basically composes the web3 provider using Alchemy/Infura's API key and user wallet's mnemonics. After some more research, I found this article which shows multiple ways of composing a web3 provider. Now I wrote a simple node app and tried with the PrivateKeySubprovider and Alchemy but got an error.
Simple index.js
file:
const keythereum = require('keythereum') // library to recover users private key from keystore
const { Web3Adapter, SafeFactory } = require('@gnosis.pm/safe-core-sdk')
const PrivateKeyWalletSubprovider = require('@0x/subproviders').PrivateKeyWalletSubprovider // subproviders import
const RPCSubprovider = require('web3-provider-engine/subproviders/rpc') // subproviders import
const Web3ProviderEngine = require('web3-provider-engine') // library to compose the web3 provider
const Web3 = require('web3')
// Getting private key
let keyObject = "<keystore>"
keyObject = JSON.parse(keyObject)
let privateKey = keythereum.recover("<password>", keyObject)
privateKey = privateKey.toString('hex')
const WALLET_ADDRESS = "<wallet address>"
const ALCHEMY_KEY = "<alchemy API key>"
// subprovider to sign the transactions
const privateKeyWalletSubprovider = new PrivateKeyWalletSubprovider(privateKey)
// subprovider to query/read blockchain
const alchemyRpcSubprovider = new RPCSubprovider({ rpcUrl: ALCHEMY_KEY })
const providerEngine = new Web3ProviderEngine()
providerEngine.addProvider(privateKeyWalletSubprovider)
providerEngine.addProvider(alchemyRpcSubprovider)
providerEngine.start() // web3 provider created
const web3Adapter = new Web3Adapter({ web3: providerEngine, signerAddress: WALLET_ADDRESS })
async function deploySafe() {
try {
const safeFactory = await SafeFactory.create({ ethAdapter: web3Adapter }) // Error happening here
console.log('[safeFactory]: ', safeFactory)
const owners = [WALLET_ADDRESS]
const threshold = 1
const safeAccountConfig = { owners, threshold }
const safeSdk = await safeFactory.deploySafe(safeAccountConfig)
console.log('[safeSdk]: ', safeSdk)
} catch (err) {
console.log('[deploySafe-error]:', err)
}
}
deploySafe()
Error:
[deploySafe-error]: TypeError: Cannot read properties of undefined (reading 'getChainId')
at Web3Adapter.getChainId (C:\Home\Dev\gnosis-venly\node_modules\@gnosis.pm\safe-core-sdk\src\ethereumLibs\Web3Adapter.ts:47:26)
at SafeFactory.init (C:\Home\Dev\gnosis-venly\node_modules\@gnosis.pm\safe-core-sdk\src\safeFactory\index.ts:76:44)
at Function.create (C:\Home\Dev\gnosis-venly\node_modules\@gnosis.pm\safe-core-sdk\src\safeFactory\index.ts:62:26)
at deploySafe (C:\Home\Dev\gnosis-venly\index.js:28:43)
at Object.<anonymous> (C:\Home\Dev\gnosis-venly\index.js:40:1)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47
Can someone help how to resolve this error? Also, is it right to use the safe SDK like this or what's the correct way of using SDK in backend for production setup?