Envoyer des transactions en utilisant viem
Ceci est un guide pour débutants sur l'envoi de transactions Ethereum à l'aide de la bibliothèque viem (s'ouvre dans un nouvel onglet). Il y a trois étapes principales pour envoyer une transaction sur la chaîne de blocs Ethereum : créer, signer et diffuser. Nous allons passer en revue ces trois étapes, en espérant répondre à toutes vos questions ! Dans ce tutoriel, nous utiliserons Alchemy (s'ouvre dans un nouvel onglet) pour envoyer nos transactions sur la chaîne Ethereum. Vous pouvez créer un compte Alchemy gratuit ici (s'ouvre dans un nouvel onglet).
REMARQUE : Ce guide concerne la signature de vos transactions sur le backend de votre application. Si vous souhaitez intégrer la signature de vos transactions sur le frontend, consultez l'API du fournisseur MetaMask (s'ouvre dans un nouvel onglet).
Les bases
Comme la plupart des développeurs de chaînes de blocs à leurs débuts, vous avez peut-être fait des recherches sur la façon d'envoyer une transaction (quelque chose qui devrait être assez simple) et vous êtes tombé sur une pléthore de guides, chacun disant des choses différentes et vous laissant un peu dépassé et confus. Si vous êtes dans ce cas, ne vous inquiétez pas ; nous y sommes tous passés à un moment donné ! Donc, avant de commencer, mettons les choses au clair :
1. Alchemy ne stocke pas vos clés privées
- Cela signifie qu'Alchemy ne peut pas signer et envoyer de transactions en votre nom. La raison en est des fins de sécurité. Alchemy ne vous demandera jamais de partager votre clé privée, et vous ne devriez jamais partager votre clé privée avec un nœud hébergé (ni avec personne d'autre d'ailleurs).
- Vous pouvez lire depuis la chaîne de blocs en utilisant l'API principale d'Alchemy, mais pour y écrire, vous devrez utiliser autre chose pour signer vos transactions avant de les envoyer via Alchemy (il en va de même pour tout autre service de nœud).
2. Qu'est-ce qu'un « signataire » (signer) ?
- Les signataires signeront les transactions pour vous en utilisant votre clé privée. Dans ce tutoriel, nous utiliserons viem (s'ouvre dans un nouvel onglet) pour signer notre transaction, mais vous pourriez également utiliser n'importe quelle autre bibliothèque Web3.
- Sur le frontend, un bon exemple de signataire serait MetaMask (s'ouvre dans un nouvel onglet), qui signera et enverra des transactions en votre nom.
3. Pourquoi dois-je signer mes transactions ?
- Chaque utilisateur qui souhaite envoyer une transaction sur le réseau Ethereum doit signer la transaction (en utilisant sa clé privée), afin de valider que l'origine de la transaction est bien celle qu'elle prétend être.
- Il est extrêmement important de protéger cette clé privée, car y avoir accès accorde un contrôle total sur votre compte Ethereum, vous permettant (ou à toute personne y ayant accès) d'effectuer des transactions en votre nom.
4. Comment protéger ma clé privée ?
- Il existe de nombreuses façons de protéger votre clé privée et de l'utiliser pour envoyer des transactions. Dans ce tutoriel, nous utiliserons un fichier
.env. Cependant, vous pourriez également utiliser un fournisseur distinct qui stocke les clés privées, utiliser un fichier de magasin de clés, ou d'autres options.
5. Quelle est la différence entre eth_sendTransaction et eth_sendRawTransaction ?
eth_sendTransaction et eth_sendRawTransaction sont toutes deux des fonctions de l'API Ethereum qui diffusent une transaction sur le réseau Ethereum afin qu'elle soit ajoutée à un futur bloc. Elles diffèrent dans la façon dont elles gèrent la signature des transactions.
eth_sendTransactionest utilisée pour envoyer des transactions non signées, ce qui signifie que le nœud auquel vous l'envoyez doit gérer votre clé privée afin de pouvoir signer la transaction avant de la diffuser sur la chaîne. Étant donné qu'Alchemy ne détient pas les clés privées des utilisateurs, ils ne prennent pas en charge cette méthode.eth_sendRawTransaction(s'ouvre dans un nouvel onglet) est utilisée pour diffuser des transactions qui ont déjà été signées. Cela signifie que vous devez d'abord signer la transaction avec votre clé privée (dans viem, en utilisantsignTransaction(s'ouvre dans un nouvel onglet) avec un compte local (s'ouvre dans un nouvel onglet)), puis passer le résultat àeth_sendRawTransaction.
Lors de l'utilisation de viem, on accède à eth_sendRawTransaction en appelant la fonction sendRawTransaction (s'ouvre dans un nouvel onglet).
C'est ce que nous utiliserons dans ce tutoriel.
6. Qu'est-ce que la bibliothèque Web3 ?
- Une bibliothèque Web3 est une enveloppe (wrapper) autour des appels JSON-RPC standards qui est très couramment utilisée dans le développement Ethereum.
- Il existe de nombreuses bibliothèques Web3 pour différents langages. Dans ce tutoriel, nous utiliserons viem (s'ouvre dans un nouvel onglet), qui est écrite en TypeScript et fonctionne dans n'importe quel projet JavaScript. Vous pouvez consulter d'autres options ici comme Ethers.js (s'ouvre dans un nouvel onglet).
Bien, maintenant que nous avons répondu à quelques-unes de ces questions, passons au tutoriel. N'hésitez pas à poser des questions à tout moment sur le Discord (s'ouvre dans un nouvel onglet) d'Alchemy !
7. Comment envoyer des transactions sécurisées, privées et optimisées en gaz ?
- Alchemy dispose d'un ensemble de ressources sur les transactions (s'ouvre dans un nouvel onglet). Vous pouvez les utiliser pour envoyer des transactions, simuler des transactions avant qu'elles ne se produisent, envoyer des transactions privées et envoyer des transactions optimisées en gaz.
- Vous pouvez également utiliser les webhooks d'Alchemy (s'ouvre dans un nouvel onglet) pour être alerté lorsque votre transaction est retirée de la mempool et ajoutée à la chaîne.
REMARQUE : Ce guide nécessite un compte Alchemy, une adresse Ethereum ou un portefeuille MetaMask, ainsi que l'installation de Node.js et npm. Si ce n'est pas le cas, suivez ces étapes :
- Créer un compte Alchemy gratuit (s'ouvre dans un nouvel onglet)
- Créer un compte MetaMask (s'ouvre dans un nouvel onglet) (ou obtenir une adresse Ethereum)
- Installer Node.js et npm (s'ouvre dans un nouvel onglet)
Étapes pour envoyer votre transaction
1. Créer une application Alchemy sur le réseau de test Sepolia
Accédez à votre tableau de bord Alchemy (s'ouvre dans un nouvel onglet) et créez une nouvelle application, en choisissant Sepolia (ou tout autre réseau de test) pour votre réseau.
2. Demander des ETH au faucet Sepolia
Suivez les instructions sur le faucet Sepolia d'Alchemy (s'ouvre dans un nouvel onglet) pour recevoir des ETH, ou utilisez l'un des autres faucets Sepolia. Les faucets distribuent de petites quantités (le faucet d'Alchemy donne 0,1 ETH par jour), ce qui est amplement suffisant pour ce tutoriel. Assurez-vous d'inclure votre adresse Ethereum Sepolia (depuis MetaMask) et non celle d'un autre réseau. Après avoir suivi les instructions, vérifiez que vous avez bien reçu les ETH dans votre portefeuille.
3. Créer un nouveau répertoire de projet et y accéder avec cd
Créez un nouveau répertoire de projet depuis la ligne de commande (terminal pour Mac) et accédez-y :
mkdir sendtx-example
cd sendtx-example
4. Installer viem (ou n'importe quelle bibliothèque Web3)
Exécutez la commande suivante dans le répertoire de votre projet pour installer viem (s'ouvre dans un nouvel onglet) :
Remarque : si vous souhaitez utiliser la bibliothèque Ethers.js, suivez les instructions ici (s'ouvre dans un nouvel onglet).
npm init -y
npm install viem
5. Installer dotenv
Nous utiliserons un fichier .env pour stocker en toute sécurité notre clé d'API et notre clé privée.
npm install dotenv
6. Créer le fichier .env
Créez un fichier .env dans le répertoire de votre projet et ajoutez ce qui suit (en remplaçant « your-api-url » et « your-private-key »)
- Pour trouver l'URL de votre API Alchemy, accédez à la page des détails de l'application que vous venez de créer sur votre tableau de bord, cliquez sur « View Key » dans le coin supérieur droit et copiez l'URL HTTP.
- Pour trouver votre clé privée à l'aide de MetaMask, consultez ce guide (s'ouvre dans un nouvel onglet). Utilisez un compte qui ne contient que des ETH de réseau de test.
API_URL="your-api-url"
PRIVATE_KEY="your-private-key"
.env ! Assurez-vous de ne jamais partager ou exposer votre fichier .env à qui que ce soit, car vous compromettriez vos secrets en le faisant. Si vous utilisez un système de contrôle de version, ajoutez votre .env à un fichier gitignore.7. Créer le fichier sendTx.js
Super, maintenant que nos données sensibles sont protégées dans un fichier .env, commençons à coder. Pour notre exemple d'envoi de transaction, nous enverrons 0,001 ETH à une autre adresse que vous contrôlez, comme un deuxième compte dans MetaMask.
Créez un fichier sendTx.js, c'est là que nous configurerons et enverrons notre exemple de transaction, et ajoutez-y les lignes de code suivantes :
require("dotenv").config({ quiet: true })
const { createPublicClient, createWalletClient, http, parseEther } = require("viem")
const { privateKeyToAccount } = require("viem/accounts")
const { sepolia } = require("viem/chains")
async function main() {
const { API_URL, PRIVATE_KEY } = process.env
const account = privateKeyToAccount(
PRIVATE_KEY.startsWith("0x") ? PRIVATE_KEY : `0x${PRIVATE_KEY}`
)
const publicClient = createPublicClient({
chain: sepolia,
transport: http(API_URL),
})
const walletClient = createWalletClient({
account,
chain: sepolia,
transport: http(API_URL),
})
const nonce = await publicClient.getTransactionCount({
address: account.address,
blockTag: "pending",
}) // le nonce commence à compter à partir de 0
const transaction = await walletClient.prepareTransactionRequest({
to: "0xYourSecondAddress", // TODO : remplacer par l'adresse à laquelle vous souhaitez envoyer de l'ETH
value: parseEther("0.001"), // 0.001 ETH
gas: 21000n,
nonce,
// champ de données facultatif pour envoyer un message ou exécuter un contrat intelligent
})
const signedTx = await walletClient.signTransaction(transaction)
try {
const hash = await walletClient.sendRawTransaction({
serializedTransaction: signedTx,
})
console.log("🎉 The hash of your transaction is:", hash)
const receipt = await publicClient.waitForTransactionReceipt({ hash })
console.log(`Transaction ${receipt.status} in block ${receipt.blockNumber}`)
} catch (error) {
console.log(
"❗Something went wrong while submitting your transaction:",
error.details ?? error.message
)
}
}
main()
Assurez-vous de remplacer 0xYourSecondAddress par l'adresse à laquelle vous souhaitez envoyer des ETH. Le script dérive votre propre adresse (d'envoi) à partir de PRIVATE_KEY, vous n'avez donc pas besoin de la saisir.
Maintenant, avant de nous lancer dans l'exécution de ce code, parlons de certains de ses composants.
account: un compte local créé à partir de votre clé privée avecprivateKeyToAccount(s'ouvre dans un nouvel onglet). La signature s'effectue sur votre machine et la clé privée n'est jamais envoyée à Alchemy.publicClientetwalletClient: des clients viem qui envoient des requêtes JSON-RPC à votre URL Alchemy. Le client public lit depuis la chaîne, et le client de portefeuille prépare et signe les transactions pour votre compte.nonce: la spécification du nonce est utilisée pour garder une trace du nombre de transactions envoyées depuis votre adresse. Nous en avons besoin pour des raisons de sécurité et pour empêcher les attaques par rejeu. Pour obtenir le nombre de transactions envoyées depuis votre adresse, nous utilisons getTransactionCount (s'ouvre dans un nouvel onglet). viem le remplirait également pour vous, mais nous le récupérons explicitement ici pour montrer d'où il vient.transaction: l'objet de transaction a quelques aspects que nous devons spécifier.prepareTransactionRequest(s'ouvre dans un nouvel onglet) remplit le reste pour nous, y compris lechainIdet les champs de frais EIP-1559maxFeePerGasetmaxPriorityFeePerGas, en fonction des conditions actuelles du réseau.to: c'est l'adresse à laquelle nous voulons envoyer des ETH.value: c'est le montant que nous souhaitons envoyer, spécifié en Wei où 10^18 Wei = 1 ETH.parseEther(s'ouvre dans un nouvel onglet) convertit un montant en ETH en Wei pour nous. Votre compte a besoin d'un peu plus que cela, car il paie également pour le gaz.gas: il existe de nombreuses façons de déterminer la bonne quantité de gaz à inclure avec votre transaction. Alchemy prend en charge les webhooks (s'ouvre dans un nouvel onglet) qui peuvent vous informer de l'activité onchain. Pour les transactions sur le Réseau principal, il est de bonne pratique de vérifier les conditions actuelles du gaz pour déterminer la bonne quantité de gaz à inclure. Un simple transfert d'ETH vers une adresse ordinaire utilise toujours exactement 21 000 gaz, ce qui est le minimum pour toute transaction, nous mettons donc 21 000 ici. Si vous omettezgas, viem l'estime pour vous.nonce: voir la définition du nonce ci-dessus. Le nonce commence à compter à partir de zéro.- [FACULTATIF] data : utilisé pour envoyer des informations supplémentaires avec votre transfert, ou pour appeler un contrat intelligent, non requis pour les transferts de solde, consultez la remarque ci-dessous.
signedTx: pour signer notre objet de transaction, nous utiliserons la méthodesignTransaction, qui le signe localement avec le compte créé à partir de notrePRIVATE_KEY.sendRawTransaction: une fois que nous avons une transaction signée, nous pouvons l'envoyer pour qu'elle soit incluse dans un bloc ultérieur en utilisantsendRawTransaction, qui appelleeth_sendRawTransaction.waitForTransactionReceipt: attend que la transaction soit incluse dans un bloc et renvoie son reçu.
Une remarque sur les données (data) Il existe deux principaux types de transactions qui peuvent être envoyées sur Ethereum.
- Transfert de solde : envoyer des ETH d'une adresse à une autre. Aucun champ de données n'est requis, cependant, si vous souhaitez envoyer des informations supplémentaires avec votre transaction, vous pouvez inclure ces informations au format HEX dans ce champ.
- Par exemple, disons que nous voulions écrire le hash d'un document IPFS sur la chaîne Ethereum afin de lui donner un horodatage immuable. Notre champ de données devrait alors ressembler à
data: toHex("IPFS hash"), en utilisanttoHex(s'ouvre dans un nouvel onglet) de viem. Et maintenant, n'importe qui peut interroger la chaîne et voir quand ce document a été ajouté.
- Par exemple, disons que nous voulions écrire le hash d'un document IPFS sur la chaîne Ethereum afin de lui donner un horodatage immuable. Notre champ de données devrait alors ressembler à
- Transaction de contrat intelligent : exécuter du code de contrat intelligent sur la chaîne. Dans ce cas, le champ de données doit contenir la fonction intelligente que vous souhaitez exécuter, ainsi que tous les paramètres.
- Pour un exemple pratique, consultez le tutoriel sur le contrat intelligent Hello World.
8. Exécuter le code en utilisant node sendTx.js
Revenez à votre terminal ou ligne de commande et exécutez :
node sendTx.js
9. Voir votre transaction sur un explorateur de blocs
Le script affiche le hachage de transaction dès que le nœud accepte la transaction, puis attend qu'elle soit incluse dans un bloc (généralement en quelques secondes) et affiche le résultat. Pour voir les détails, collez le hash dans un explorateur de blocs Sepolia tel que Sepolia Etherscan (s'ouvre dans un nouvel onglet) ou Blockscout (s'ouvre dans un nouvel onglet). Vous pourrez y voir la transaction passer de l'état en attente à incluse, et voir le montant, les frais et le bloc dans lequel elle a atterri.
Si vous voyez plutôt une erreur insufficient funds, votre compte n'a pas assez d'ETH Sepolia pour couvrir la valeur plus le gaz. Retournez à l'étape 2 et demandez-en davantage à un faucet.
Youpi ! Vous venez d'envoyer votre première transaction Ethereum en utilisant Alchemy 🎉
Pour des commentaires et des suggestions sur ce guide, veuillez envoyer un message à Elan sur le Discord (s'ouvre dans un nouvel onglet) d'Alchemy !
Publié à l'origine par Alchemy.