Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungFliproom: a room changeover is a content problem(21.09.2026 um 04:10 Uhr)
Sichere ProgrammierungNova Adiutrix: My Second Agent Built My First Project's To-Do List(21.09.2026 um 04:11 Uhr)
IT Security ToolsAntiphishing v35456910988(21.09.2026 um 02:35 Uhr)
IT Security Toolsbrave-browser v1.98.12(21.09.2026 um 03:35 Uhr)
Sichere ProgrammierungFliproom: a room changeover is a content problem(21.09.2026 um 04:10 Uhr)
Sichere ProgrammierungNova Adiutrix: My Second Agent Built My First Project's To-Do List(21.09.2026 um 04:11 Uhr)
IT Security ToolsAntiphishing v35456910988(21.09.2026 um 02:35 Uhr)
IT Security Toolsbrave-browser v1.98.12(21.09.2026 um 03:35 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Build a Soroban smart contract deployer using Next.js

Reagiere als Erste:r — dein Feedback zählt!

In this article, we will learn how to build a dapp that can deploy smart contracts. Usually dapps interact with smart contracts by invoking its methods, but I wanted to explore how contracts actually get deployed on a blockchain network. Hence, I decided to build a web interface for a smart contract deployer as an alterantive to the usual CLI.

Introduction

To deploy a new smart contract on the Stellar network, we essentially need to do two things:

  • Upload the contract wasm file on the network. This is what soroban contract install does. Thetransaction that uploads the wasm file returns the hash of the wasm file. This is needed in the next step
  • Creating the contract itself. This is what soroban contract deploy does. This creates a contract instance linked to the wasm file that we uploaded. This step needs to be provided with the wasm hash we receive in the previous step, since the contract needs to know which wasm binary to execute.

Getting started

You just need Node.js v18 or higher for this project. We'll be using Next.js and use its server side rendering capabilities to contact the Soroban RPC and deploy the contract.

Initialize the project:

npx create-next-app@latest

I've decided to use the Pages router here but you can use the App router if you wish to.

We'll need to install the following packages as well:

npm install --save stellar-sdk formidable

Building the deployer

Now lets start building our UI. We need two things to deploy a new contract:

  • The private key of a Stellar account.
  • The wasm executable

This means we need a password field (since its a private key) and a file upload field. Lets go ahead and build that:

return (
    <>
        <div>
            <NavBar />
        </div>
        <div className='container'>
            <h2> Your private key </h2>
            <p> (its not logged or stored! 😉) </p>
            <input type="password" value={textField} onChange={handleTextChange} />
            <h2> Upload the wasm file </h2>
            <input type="file" onChange={handleFileChange} />
            {isLoading ? (
                <div className="spinner"></div> // Spinner element
            ) : (
                <button onClick={handleSubmit} disabled={isLoading}>Deploy</button>
            )}
            <Modal isOpen={isModalOpen} onClose={closeModal} wasmHash={wasmHash} contractID={contractID} />
        </div>
    </>
);

Now lets a handler for the "Deploy" button. The handler will call a server side function with the private key and the wasm file. It'll get back the contract ID and the wasm hash.

const handleSubmit = async () => {
    // activate spinner
    setIsLoading(true);
    if (file) {
        const formData = new FormData();
        formData.append('file', file);
        formData.append('textField', textField);

        try {
            // Send the file and the private key to the server side function.
            const response = await fetch('/api/deployer', {
                method: 'POST',
                body: formData,
            });
            console.log(response.statusText)
            const body = await response.json();
            console.log(body);
            setWasmHash(body.wasmHash);
            setContractID(body.id);
            setModalOpen(true);
        } catch (error) {
            console.log(error);
        } finally {
            // deactivate spinner
            setIsLoading(false);
        }
    } else {
        // deactivate spinner
        setIsLoading(false);
    }
};

Now lets take a look at the server side handler that actually deploys the contract:

export default function handler(req: NextApiRequest, res: NextApiResponse<ContractData | String>) {
    if (req.method === 'POST') {
        const form = new formidable.IncomingForm();

        form.parse(req, async (err, fields, files) => {
            if (err) {
                console.error('Error parsing the form:', err);
                return res.status(500).send('Error parsing the form');
            }

            try {
                // Get the private key
                const pk = fields.textField[0];

                const file = files.file;
                // Get the wasm file buffer
                const data = fs.readFileSync(file[0].filepath);
            } catch (error) {
                console.error('Error processing form:', error);
                res.status(500).send('Error processing form');
            }
        });

}

Here we parse the request form and extract the private key and the wasm file. Now its time to constrcut a keypair and upload the wasm file:

    let op = sdk.Operation.uploadContractWasm({ wasm: data });

    // To store the contract hash returned by the RPC.
    let contractHash = '';
    const sourceKeypair = sdk.Keypair.fromSecret(pk);
    const sourcePublicKey = sourceKeypair.publicKey();
    const account = await server.getAccount(sourcePublicKey);

    // Build, prepare, sign and send the upload contract wasm transaction.
    let tx = new sdk.TransactionBuilder(account, { fee: sdk.BASE_FEE })
        .setNetworkPassphrase(sdk.Networks.FUTURENET)
        .setTimeout(30)
        .addOperation(op)
        .build();
    try {
        const preparedTransaction = await server.prepareTransaction(tx);
        preparedTransaction.sign(sourceKeypair);
        const uploadResp = await server.sendTransaction(preparedTransaction);
        while (true) {
            const val = await server.getTransaction(uploadResp.hash);
            if (val.returnValue === undefined || val.returnValue === null) {
                console.log("continuing");
                continue
            } else {
                // The first 16 characters are of no importance.
                contractHash = val.returnValue.toXDR('hex').slice(16);
                console.log("contract hash", contractHash);
                break;
            }
        }
    } catch (error) {
        console.log("error uploading", error);
        return res.status(500).send('Error uploading the contract wasm file');
    }

After we have uploaded the wasm file to the network, lets create the contract:

        const hash = sdk.hash(data);

        // The operation to create a contract on the network.
        let contractOp = sdk.Operation.createCustomContract({
            address: new sdk.Address(sourcePublicKey),
            wasmHash: hash,
        });

        // To store the contract ID.
        let contractID = '';

        // Build, prepare, sign and send the create contract transaction.
        let contractTx = new sdk.TransactionBuilder(account, { fee: sdk.BASE_FEE })
            .setNetworkPassphrase(sdk.Networks.FUTURENET)
            .setTimeout(30)
            .addOperation(contractOp)
            .build();
        try {
            const preparedTransaction = await server.prepareTransaction(contractTx);
            preparedTransaction.sign(sourceKeypair);
            const contractResp = await server.sendTransaction(preparedTransaction);
            while (true) {
                const val = await server.getTransaction(contractResp.hash);
                if (val.returnValue === undefined || val.returnValue === null) {
                    console.log("continuing create");
                    continue
                } else {
                    contractID = sdk.Address.contract(val.returnValue.address().contractId()).toString();
                    console.log("contract id", contractID);
                    break;
                }
            }
        } catch (error) {
            console.log("error creating", error);
            return res.status(500).send('Error deploying the contract');
        }

Now lets return the contract information back to the UI so that it can display it to the user:

    res.status(201).send({
        wasmHash: contractHash,
        id: contractID
    });

Now we just have one final thing remaining: a modal to display the contract infomation. Lets go ahead and build that:

// Modal to display the wasm hash and contract ID.
const Modal = ({ isOpen, onClose, wasmHash, contractID }) => {
    if (!isOpen) {
        return null;
    }

    return (
        <div className="modal-backdrop">
            <div className="modal">
                <h2> Contract deployed! </h2>
                <br></br>
                <h3>WASM hash: {wasmHash}</h3>
                <h3>Contract ID: {contractID}</h3>
                <div className="modal-actions">
                    <button onClick={onClose}>Close</button>
                </div>
            </div>
        </div>
    );
};

Now we can use this in our main component:

    return (
        <>
            <div>
                <NavBar />
            </div>
            <div className='container'>
                <h2> Your private key </h2>
                <p> (its not logged or stored! 😉) </p>
                <input type="password" value={textField} onChange={handleTextChange} />
                <h2> Upload the wasm file </h2>
                <input type="file" onChange={handleFileChange} />
                {isLoading ? (
                    <div className="spinner"></div> // Spinner element
                ) : (
                    <button onClick={handleSubmit} disabled={isLoading}>Deploy</button>
                )}
                <Modal isOpen={isModalOpen} onClose={closeModal} wasmHash={wasmHash} contractID={contractID} />
            </div>
        </>
    );

Conclusion

And here we are, with a web GUI that can deploy Soroban smart contracts. We learn how smart contracts get deployed and the necessary transactions and steps involved.

Good luck on your dapp building journrey! ❤️

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Build a Soroban smart contract deployer using Next.js

Thematisch verwandte Begriffe: Build, Soroban, smart, contract · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-93977 | A vulnerability was determined in code-projects Assessment Management 1.…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick