Recettes de dApp
Portefeuille
Connectez le portefeuille à l'application décentralisée (dApp).
Le package @alephium/web3-react
fournit des composants React et des hooks puissants pour connecter un portefeuille à votre dApp.
Connectez le portefeuille
// Alephium Context Provider
<AlephiumWalletProvider theme='retro' network='devnet'>
<YourComponent />
</AlephiumWalletProvider>
// Bouton de connexion
<AlephiumConnectButton />
// Hook de portefeuille
const { connectionStatus, signer, account } = useWallet()
// Hook de solde
const { balance } = useBalance()
// Hook de connexion utilisé par `<AlephiumConnectButton />` sous le capot
const { connect, disconnect } = useConnect()
Portefeuilles du SDK Web3
Le SDK fournit quelques portefeuilles de base pour les développeurs.
Portefeuille HD/Portefeuille de clé privée
// Portefeuille HD
const mnemonic = bip39.generateMnemonic(128)
const hdWallet = new HDWallet({ mnemonic })
// Portefeuille de clé privée
const wallet0 = new PrivateKeyWallet({ privateKey })
const wallet1 = PrivateKeyWallet.Random()
const wallet2 = PrivateKeyWallet.FromMnemonic({ mnemonic })
Portefeuille de test
La bibliothèque @alephium/web3-test
fournit des portefeuilles pratiques à des fins de test.
Portefeuille de test
Token
Récupérer les métadonnées du jeton fongible
Récupérer l'offre en circulation / l'offre totale d'un jeton
Le code suivant récupère l'offre totale programmée par le développeur du jeton. Notez que la vérification réelle du contrat est nécessaire pour la fiabilité.
Il n'y a pas de fonction directe pour l'offre en circulation suivant la norme ERC20.
TODO
interroger le montant d'émission du jeton dans le backend de l'explorateur pour fournir des informations plus fiables.
Récupérer les métadonnées du NFT
Récupérer les métadonnées de la collection
Contrat
Récupérer l'état du contrat
Lors de l'utilisation de la commande npx @alephium/cli compile
our compiler un contrat, elle générera du code TypeScript basé sur le code du contrat.
Prenons l'exemple du contrat TokenFaucet,
ici se trouve le code TypeScript généré.
Nous pouvons utiliser le code TypeScript généré pour récupérer l'état du contrat :
Token Faucet/Récupérer l'état du contrat
import { TokenFaucet } from 'artifacts/ts' // Note that you may need to change the import path according to your project directory structure
import { web3, NodeProvider } from '@alephium/web3'
const nodeUrl = 'http://127.0.0.1:12973'
const nodeProvider = new NodeProvider(nodeUrl)
web3.setCurrentNodeProvider(nodeProvider)
const tokenFaucetAddress = 'y1btMZHTvMvHEqLTdx1JHvEXq3tmVfqsY2rwM669upiT'
const tokenFaucet = TokenFaucet.at(tokenFaucetAddress)
const contractState = await tokenFaucet.fetchState()
// Les noms dans `contractState.fields` sont les mêmes que les noms de champ dans le contrat TokeFaucet
const { symbol, name, decimals, supply, balance } = contractState.fields
// Vous pouvez également obtenir les actifs détenus par le contrat
const { alphAmount, tokens } = contractState.asset
Appeler une méthode de contrat
Vous pouvez utiliser le code TypeScript généré pour appeler les méthodes du contrat, c'est similaire à eth_call
dans Ethereum :
Token Faucet/Appeler une méthode de contrat
import { TokenFaucet } from 'artifacts/ts'
import { web3, NodeProvider } from '@alephium/web3'
const nodeUrl = 'http://127.0.0.1:12973'
const nodeProvider = new NodeProvider(nodeUrl)
web3.setCurrentNodeProvider(nodeProvider)
const tokenFaucetAddress = 'y1btMZHTvMvHEqLTdx1JHvEXq3tmVfqsY2rwM669upiT'
const tokenFaucet = TokenFaucet.at(tokenFaucetAddress)
const totalSupply = await tokenFaucet.methods.getTotalSupply()
S'abonner aux événements du contrat
Dans le contrat TokenFaucet,
nous avons défini un événement Withdraw.
Chaque fois que la fonction withdraw
est appelée, le contrat émettra un événement Withdraw
.
Nous pouvons nous abonner aux événements de retrait en utilisant l'approche suivante:
token.ral
import { TokenFaucet, TokenFaucetTypes } from 'artifacts/ts'
import { EventSubscribeOptions } from '@alephium/web3'
// `TokenFaucetTypes.WithdrawEvent` est un type TypeScript généré
const options: EventSubscribeOptions<TokenFaucetTypes.WithdrawEvent> = {
// Nous spécifions l'intervalle de sondage à 4 secondes, ce qui interrogera le contrat pour de nouveaux événements toutes les 4 secondes
pollingInterval: 4000,
// Le `messageCallback` sera appelé chaque fois que nous recevons un nouvel événement
messageCallback: (event: TokenFaucetTypes.WithdrawEvent): Promise<void> => {
console.log(`Withdraw(${event.fields.to}, ${event.fields.amount})`)
return Promise.resolve()
},
// Le `errorCallback` sera appelé en cas d'erreur, ici nous désabonnons l'abonnement et journalisons l'erreur
errorCallback: (error, subscription): Promise<void> => {
console.error(error)
subscription.unsubscribe()
return Promise.resolve()
},
// Le rappel `onEventCountChanged` est un paramètre facultatif qui sera appelé lorsque le nombre d'événements du contrat change
onEventCountChanged: (eventCount): Promise<void> => {
},
}
// Nous nous abonnons aux événements de contrat à partir du nombre d'événements 0.
// Nous pouvons également persister le nombre d'événements actuel dans le rappel `onEventCountChanged`,
// nous permettant de nous abonner depuis le dernier nombre d'événements pour l'abonnement suivant.
const fromEventCount = 0
const subscription = tokenFaucet.subscribeWithdrawEvent(options, fromEventCount)
// Désabonner l'abonnement
subscription.unsubscribe()
Fonctions de test avec temps de bloc simulé
Il est possible de tester les fonctions avec un temps de bloc simulé dans les tests unitaires. Pour les tests d'intégration basés sur le testnet ou le devnet, il n'y a cependant aucun moyen de changer le temps de bloc.
Voici un exemple simple:
Token Faucet
Enregistrer des messages de débogage
Ralph prend en charge les messages de débogage en émettant l'événement intégré Debug
. Notez que de tels événements sont ignorés sur le mainnet.
Contrat Ralph simple
// Contrat Ralph simple
Contract Debug() {
pub fn debug() -> () {
emit Debug(`Hello, ${nullContractAddress!()}!`)
}
}
// Test unitaire en TypeScript
const result = await Debug.tests.debug()
// La ligne suivante apparaîtra dans la sortie de la console et dans les journaux du nœud complet:
// Debug - tgx7VNFoP9DJiFMFgXXtafQZkUvyEdDHT9ryamHJYrjq - Bonjour, tgx7VNFoP9DJiFMFgXXtafQZkUvyEdDHT9ryamHJYrjq!
// Récupérer tous les messages de débogage
console.log(result.debugMessages)
Transaction
Interroger le statut de la transaction
Vous pouvez interroger le statut de la transaction en utilisant l'approche suivante:
NodeProvider
import { NodeProvider } from '@alephium/web3'
const nodeUrl = 'http://127.0.0.1:12973'
const nodeProvider = new NodeProvider(nodeUrl)
const txId = '919d4e4b1080d74beb56a1f78ea7c0569a358e3ea3988058987cc1addf4b93cc'
const txStatus = await nodeProvider.transactions.getTransactionsStatus({ txId })
Vous pouvez différencier le statut de la transaction en utilisant txStatus.type
:
MemPooled
: cela signifie que la transaction se trouve dans le mempoolConfirmed
: la transaction a été confirmée, et vous pouvez obtenir les confirmations en utilisanttxStatus.chainConfirmations
TxNotFound
: la transaction n'existe pas
Hooks
Le package @alephium/web3-react
fournit plusieurs hooks pour faciliter le développement des interfaces utilisateur frontend.
useWalletConfig
useWalletConfig
import { useWalletConfig } from '@alephium/web3-react'
export function Component() {
const { network, setNetwork, addressGroup, setAddressGroup } = useWalletConfig()
return <div>
<button onClick={() => setNetwork('testnet')}>Network: {network}</button>
<button onClick={() => setAddressGroup(3)}>Address group: {addressGroup}</button>
</div>
}
Le hook useWalletConfig
renvoie les configurations du bouton de connexion et des fonctions utilitaires pour mettre à jour ces configurations.
useWallet
useWallet
import { useWallet, Wallet } from '@alephium/web3-react'
function Component() {
const { account, connectionStatus } = useWallet()
if (connectionStatus === 'connecting') return <div>Connecting</div>
if (connectionStatus === 'disconnected') return <div>Disconnected</div>
// connecté
return <div>{account}</div>
}
Si la valeur de retour est undefined
, cela indique que le portefeuille n'est pas connecté. Le portefeuille renvoyé a les champs suivants:
wallet.signer
: vous pouvez utiliser le signataire pour signer des transactionswallet.account
: il s'agit du compte actuellement connectéwallet.nodeProvider
: vous pouvez utiliser le fournisseur de nœuds pour communiquer avec le nœud complet, notez que cette valeur peut êtreundefined
useBalance
useBalance
Le hook useBalance
renvoie deux valeurs:
balance
: le solde actuel du compte connectéupdateBalanceForTx
: cela est utilisé pour mettre à jour le solde lorsque l'utilisateur effectue une transaction. Il prend un identifiant de transaction en paramètre, et il mettra à jour le solde une fois cette transaction confirmée.
useTxStatus
useTxStatus
Le hook useTxStatus
accepte également un paramètre de rappel optionnel de type (txStatus: node.TxStatus) => Promise<any>
, il sera appelé après chaque requête de statut de transaction.
Utilitaires
Limitation du taux
NodeProvider
est utilisé pour communiquer avec le nœud complet lors du développement d'une dApp,
et vous pouvez utiliser les API services fournis par Alephium.
Mais tous les API sont limités en termes de taux pour éviter le spam. Donc, si le client envoie trop de requêtes dans un laps de temps donné, il recevra l'erreur HTTP 429.
Vous pouvez utiliser le fetch-retry pour résoudre ce problème :
fetchRetry
import * as fetchRetry from 'fetch-retry'
// Nous spécifions jusqu'à 10 nouvelles tentatives, avec un délai de 1 seconde entre chaque tentative.
const retryFetch = fetchRetry.default(fetch, {
retries: 10,
retryDelay: 1000
})
const nodeProvider = new NodeProvider('node-url', undefined, retryFetch)
Bouton de connexion personnalisé
@alephium/web3-react
fournit le composant AlephiumConnectButton
pour faciliter le développement des interfaces utilisateur,
vous pouvez également utiliser AlephiumConnectButton.Custom
pour personnaliser le style du bouton de connexion:
Alephium Bouton de connexion
import { AlephiumConnectButton } from '@alephium/web3'
function CustomWalletConnectButton = () => {
return (
<AlephiumConnectButton.Custom>
{({ isConnected, disconnect, show, account }) => {
return isConnected ? (
<button onClick={disconnect}>
Disconnect
</button>
) : (
<button onClick={show}>
Connect
</button>
)
}}
</AlephiumConnectButton.Custom>
)
}