Zum Inhalt

Mit Verträgen interagieren

Alephiums Full Node bietet eine Reihe von APIs zum Interagieren mit den bereitgestellten Verträgen. Diese Interaktionen können je nachdem, ob sie beabsichtigen, den Zustand der Blockchain zu aktualisieren, in zwei Kategorien unterteilt werden: Vertragsaufrufe sind schreibgeschützte Interaktionen, die gebührenfrei sind und sofort ausgeführt werden, wobei das Ergebnis sofort an den Aufrufer zurückgegeben wird. TxScript-Transaktionen hingegen aktualisieren den Zustand der Blockchain, erfordern Gas und werden ausgeführt, wenn Transaktionen abgebaut werden, wobei nur die Transaktions-IDs an den Aufrufer zurückgegeben werden.

Die direkte Interaktion mit Verträgen über die Full-Node-API kann mühsam sein. Alephiums Web3 SDK abstrahiert viele Details, indem es Wrapper-Code für Verträge und Transaktionsskripte generiert. Lassen Sie uns seine Nützlichkeit anhand des TokenFaucet Vertrags demonstrieren, der im Getting started-Leitfaden diskutiert wird:

token_faucet.ral
Rust
import "std/fungible_token_interface"

// Definiert einen Vertrag namens TokenFaucet.
// Ein Vertrag ist eine Sammlung von Feldern (sein Zustand) und Funktionen.
// Einmal bereitgestellt, befindet sich ein Vertrag an einer spezifischen Adresse auf der Alephium-Blockchain.
// Vertragsfelder werden dauerhaft im Vertragsspeicher gespeichert.
// Ein Vertrag kann bei seiner Bereitstellung eine anfängliche Menge an Token ausgeben.
Contract TokenFaucet(
    symbol: ByteVec,
    name: ByteVec,
    decimals: U256,
    supply: U256,
    mut balance: U256
) implements IFungibleToken {


    // Ereignisse ermöglichen das Protokollieren von Aktivitäten auf der Blockchain.
    // Alephium-Clients können Ereignissen lauschen, um auf Änderungen des Vertragszustands zu reagieren.
    event Withdraw(to: Address, amount: U256)

    enum ErrorCodes {
        InvalidWithdrawAmount = 0
    }


    // Eine öffentliche Funktion, die die anfängliche Versorgung mit dem Token des Vertrags zurückgibt.
    // Beachten Sie, dass das Feld als Betrag des ausgegebenen Tokens initialisiert werden muss.
    pub fn getTotalSupply() -> U256 {
        return supply
    }


    // Eine öffentliche Funktion, die das Symbol des Tokens zurückgibt.
    pub fn getSymbol() -> ByteVec {
        return symbol
    }

    // Eine öffentliche Funktion, die den Namen des Tokens zurückgibt.
    pub fn getName() -> ByteVec {
        return name
    }


    // Eine öffentliche Funktion, die die Dezimalstellen des Tokens zurückgibt.
    pub fn getDecimals() -> U256 {
        return decimals
    }

    // Eine öffentliche Funktion, die den aktuellen Kontostand des Vertrags zurückgibt.
    pub fn balance() -> U256 {
        return balance
    }


    // Eine öffentliche Funktion, die Token an jeden überträgt, der sie aufruft.
    // Die Funktion ist mit updateFields = true gekennzeichnet, da sie die Vertragsfelder ändert.
    // Die Funktion ist als Verwendung von Vertragsvermögenswerten gekennzeichnet, da sie diese verwendet
    @using(assetsInContract = true, updateFields = true, checkExternalCaller = false)
    pub fn withdraw(amount: U256) -> () {
        // Debug-Ereignisse können bei der Fehleranalyse hilfreich sein.
        emit Debug(`The current balance is ${balance}`)


        // Stellen Sie sicher, dass der Betrag gültig ist.
        assert!(amount <= 2, ErrorCodes.InvalidWithdrawAmount)
        // Funktionen mit dem Suffix ! sind integrierte Funktionen.
        transferTokenFromSelf!(callerAddress!(), selfTokenId!(), amount)
        // Ralph erlaubt keine Unterlauf.
        balance = balance - amount

        // Das zuvor definierte Ereignis auslösen.
        emit Withdraw(callerAddress!(), amount)
    }
}

Der VertragTokenFaucet verfügt über 5 öffentliche Funktionen, die nur den Vertragszustand lesen: getTotalSupply, getSymbol, getName, getDecimals und balance. Er hat auch eine Funktion namens withdraw, die nicht nur den Vertragszustand aktualisiert, sondern auch Vermögenswerte überträgt.

Nachdem der Vertrag TokenFaucet kompiliert wurde, wird eine entsprechende TypeScript-Klasse generiert. Wir können eine Instanz dieser Klasse erhalten, nachdem wir sie auf dem Devnet bereitgestellt haben:

TypeScript
import { DUST_AMOUNT } from '@alephium/web3'
import { getSigner } from '@alephium/web3-test'
import { TokenFaucet, TokenFaucetTypes, Withdraw } from '../artifacts/ts'

const signer = await getSigner()
const deployResult = await TokenFaucet.deploy(signer, {
    initialFields: {
    symbol: stringToHex('TF'),
    name: stringToHex('TokenFaucet'),
    decimals: 18n,
    supply: 10n ** 18n,
    balance: 10n
    }
})

const tokenFaucet = deployResult.contractInstance

Contract Aufruf

Innerhalb der TokenFaucet TypeScript-Klasse generiert das Alephium-SDK Methoden für alle reinen Funktionen im TokenFaucet-Vertrag. Sie können genau wie reguläre TypeScript-Funktionen aufgerufen werden:

TypeScript
const getNameResult = await tokenFaucet.methods.getName()
console.log(`name: ${hexToString(getNameResult.returns)}`)  // name: TokenFaucet

const getDecimalsResult = await tokenFaucet.methods.getDecimals()
console.log(`decimals: ${getDecimalsResult.returns)}`)      // decimals: 18

Beachten Sie, dass die Ergebnisse der Vertragsaufrufe sofort zurückgegeben werden und weder Gas noch Signaturen erforderlich sind.

Das Alephium-SDK generiert auch Code für das gleichzeitige Aufrufen mehrerer reiner Funktionen, was die Anzahl der Netzwerkanfragen reduziert:

TypeScript
const result = await tokenFaucet.multicall({
    getSymbol: {},
    getName: {},
    getDecimals: {},
    getTotalSupply: {}
})

console.log(`name: ${hexToString(result.getName.returns)}`)       // name: TokenFaucet
console.log(`symbol: ${hexToString(result.getSymbol.returns)}`)   // symbol: TF
console.log(`decimals: ${result.getDecimals.returns}`)            // decimals: 18
console.log(`total supply: ${result.getTotalSupply.returns}`)     // total supply: 10

TxScript Transaktionen

Der Vertrag TokenFaucet hat auch eine Funktion namens withdraw, die das Token vom Faucet zum Aufrufer überträgt und den Kontostand aktualisiert. Wenn wir die Funktion withdraw aufrufen, müssen wir sie als Transaktion mit TxScript ausführen:

Rust
TxScript Withdraw(token: TokenFaucet, amount: U256) {
    // Die Funktion withdraw des Token-Vertrags aufrufen.
    token.withdraw(amount)
}

Das SDK von Alephium generiert auch eine entsprechende TypeScript-Klasse für das Withdraw-Transaktionsskript nach dem compilation, das wir verwenden können, um die Transaktion auszuführen:

TypeScript
const signer = await getSigner()
const withdrawResult = await Withdraw.execute(signer, {
  initialFields: { token: tokenFaucet.contractId, amount: 2n },
  attoAlphAmount: DUST_AMOUNT * 2n
})
console.log(`tx id: ${withdrawResult.txId}`)  // tx id: xxxx

Wir übergeben die initialFields, wie sie im Withdraw-Transaktionsskript definiert sind, sowie genug attoAlphAmount, um die Gasgebühren sowie den Staubbetrag für den Erhalt von Token abzudecken.

Beachten Sie, dass ein signer erforderlich ist, um die Transaktion zu signieren. Das Ausführungsergebnis des Withdraw-Skripts enthält eine Transaktions-ID, die später verwendet werden kann, um den Status der Transaktion abzufragen. Einige andere nützliche Informationen im Ausführungsergebnis sind:

  • unsignedTx: Serialisierte Version der ungesignierten Transaktion
  • signature: Signatur des Signierenden für die Transaktion
  • gasAmount: Gasgebühr der Transaktion

Eine Funktion, die aus einem TxScript ausgeführt wird, kann dem Aufrufer keine Werte direkt zurückgeben, da die Transaktion später verarbeitet wird und das Ergebnis nicht deterministisch ist und vom zukünftigen Zustand der Blockchain abhängt, wenn die Transaktion abgebaut wird. Stattdessen werden häufig Events verwendet, um Einblicke in die Vertragsaktivitäten zu erhalten.


Events Subscription

Die withdraw-Funktion für den TokenFaucet-Vertrag löst ein Withdraw-Ereignis aus, das den Empfänger und den Betrag des abgehobenen Tokens enthält.

Rust
emit Withdraw(callerAddress!(), amount)

Ereignisse wie dieses sind für dApps sehr nützlich, um Vertragsaktivitäten zu verfolgen. Alephiums Web3 SDK stellt eine Reihe von Funktionen zur Interaktion mit den Ereignissen eines Vertrags bereit. Hier ist, wie wir das Withdraw -Ereignis abonnieren können, das von der withdraw -Funktion im TokenFaucet-Vertrag ausgelöst wird:

TypeScript
// Abonnieren Sie das `Withdraw`- Ereignis.
tokenFaucet.subscribeWithdrawEvent({
    pollingInterval: 500,
    messageCallback: (event: TokenFaucetTypes.WithdrawEvent): Promise<void> => {
    console.log('got withdraw event:', event)
    return Promise.resolve()
    },
    errorCallback: (error: any, subscription): Promise<void> => {
    console.log(error)
    subscription.unsubscribe()
    return Promise.resolve()
    }
})

Wenn mehr als ein Ereignis vom TokenFaucet-Vertrag ausgelöst wird, wird auch eine Funktion namens subscribeAllEvents generiert, um sich für alle Ereignisse zu abonnieren, die vom Vertrag ausgelöst werden.


Weiterführende Literatur

Alephiums Web3 SDK bietet benutzerfreundliche Abstraktionen über die APIs des vollständigen Knotens von Alephium. Weitere Informationen zu den APIs finden Sie in der OpenAPI Dokumentation.

Lesen Sie eine ausführlichere Erklärung zu TxScript hier, , einem einzigartigen Merkmal in Alephium, das eine flexiblere und effizientere Möglichkeit bietet, Transaktionen zu erstellen, die mit Smart Contracts interagieren.

Ereignisse sind entscheidend für den Aufbau von dApps, weitere Informationen finden Sie hier.