Use a dWallet on Ethereum
After creating a dWallet, you can derive the dWallet's Ethereum address, create transactions from that address, sign them with the dWallet, and broadcast the signed transactions to the Ethereum network.
Setup
First, we need to set up the environment. Begin by importing the necessary functions:
import {
DWalletClient,
SuiHTTPTransport,
} from '@dwallet-network/dwallet.js/client'
import {Ed25519Keypair} from '@dwallet-network/dwallet.js/keypairs/ed25519'
import {requestSuiFromFaucetV0 as requestDwltFromFaucetV0} from '@dwallet-network/dwallet.js/faucet'
import {ethers} from 'ethers'
import * as elliptic from 'elliptic'
import {
createDWallet,
getOrCreateEncryptionKey,
storeEncryptionKey,
setActiveEncryptionKey,
EncryptionKeyScheme,
createActiveEncryptionKeysTable,
createPartialUserSignedMessages,
approveAndSign,
} from '@dwallet-network/dwallet.js/signature-mpc'
import {
recovery_id_keccak256 as recoveryIdKeccak256,
} from '@dwallet-network/signature-mpc-wasm';
Get the dWallet's Ethereum Address
To create transactions on the Ethereum network, we need an Ethereum address.
The Ethereum address is generated by hashing your public key in sha3
format and taking the last 40 bytes of the
result.
// Get the dWallet object.
const dwallet = await client.getObject({id: dwalletID, options: {showContent: true}});
if (dwallet?.data?.content?.dataType == "moveObject") {
// Get the public key.
// @ts-ignore
const pubkeyhex = Buffer.from(dwallet?.data?.content?.fields["public_key"]).toString("hex");
// The public key is in its compressed form, so we uncompress it, as the
// address is derived from the uncompressed public key.
const ec = new elliptic.ec("secp256k1");
const publicKeyUncompressed = ec.keyFromPublic(pubkeyhex, "hex").getPublic(false, "hex");
let pubkey = Buffer.from(publicKeyUncompressed, "hex");
// Here we are doing keccak256 hashing of our ECDSA public key.
const ethereumAddress = ethers.getAddress(ethers.keccak256(pubkey).slice(-40));
console.log("dWallet Ethereum address is", ethereumAddress);
}
Access the Ethereum Network
We need a service that offers a web API for accessing the Ethereum blockchain.
Providers allow connecting to the blockchain, simplifying development.
In the following example, we use EtherscanProvider
with the Sepolia network,
which is Ethereum's proof-of-authority testnet.
const provider = new ethers.EtherscanProvider(ethers.Network.from("sepolia"), "");
// Get chainId from network.
const chainId = (await provider.getNetwork()).chainId;
Sign a Tx
You can create transactions using the
ethers
library documentation on Transactions.
Once we have the transaction object, we sign the bytes of the hash generated from the transaction.
const tx = new ethers.Transaction()
// * fill the tx parameters here *
// `tx.unsignedSerialized` is a hex string starting with `0x`, so we remove it by slicing the first two
// characters before parsing it as a hex string into a byte array.
const bytes = Uint8Array.from(
Buffer.from(tx.unsignedSerialized.slice(2), 'hex'),
)
// Sign the transaction bytes
const signMessagesIdKECCAK256 = await createPartialUserSignedMessages(
dkg?.dwalletID!,
dkg?.decentralizedDKGOutput!,
new Uint8Array(dkg?.secretKeyShare!),
[bytes],
'KECCAK256',
keypair,
client,
)
const sigKECCAK256 = await approveAndSign(
dkg?.dwalletCapID!,
signMessagesIdKECCAK256!,
[bytes],
dkg?.dwalletID!,
'KECCAK256',
keypair,
client,
)
const sig = Buffer.from(sigKECCAK256[0]).toString('hex')
const recoveryId =
'0' +
recoveryIdKeccak256(
// @ts-ignore
dwallet?.data?.content?.fields['public_key'],
bytes,
sigKECCAK256[0],
).toString(16)
// Serialized signature in a formate r[32-byte]-s[32-byte]-v[1-byte] where v is recovery ID.
tx.signature = '0x' + sig + recoveryId
Broadcast the Tx
After signing the transaction with our dWallet and updating the tx
object with the correct signature format, the final
step is to broadcast the transaction to the Ethereum blockchain.
const response = await provider.broadcastTransaction(tx.serialized);
console.log(`Transaction successful with hash: ${response.hash}`);
And that is it! You can view the transaction at: https://sepolia.etherscan.io/tx/<response.hash>