Skip to content

Creating Transactions Using Typed Descriptors in JavaScript⚓︎

Transactions are a fundamental part of the Symbol blockchain, because most interactions with the network happen through them.

All JavaScript examples throughout the tutorials use the SymbolTransactionFactory.create method to create transactions, due to its compact syntax. However, this method is not type-safe: it accepts a generic object and depends on it having the correct fields.

This page shows how to use SymbolFacade.createTransactionFromTypedDescriptor instead. This alternative accepts well-defined parameters, offering better type safety and improved IDE support.

The code presented here is the same as in the Creating a Transfer Transaction tutorial, with the only difference being the transaction creation step. For brevity, only that section is shown here. The rest of the process, including signing and announcing the transaction, remains unchanged.

    // Build the transaction
    const typedDescriptor =
        new descriptors.TransferTransactionV1Descriptor(
            facade.network.publicKeyToAddress(signerKeyPair.publicKey),
            [
                new descriptors.UnresolvedMosaicDescriptor(
                    new models.UnresolvedMosaicId(
                        generateMosaicAliasId('symbol.xym')),
                    new models.Amount(1_000_000n) // 1 XYM
                )
            ]
        );
    const transaction = facade.createTransactionFromTypedDescriptor(
        typedDescriptor, signerKeyPair.publicKey, 0, 2 * 60 * 60);
    transaction.fee = new models.Amount(feeMult * transaction.size);

Download the full tutorial code.

Creation Process⚓︎

Transactions are created in a type-safe manner in two steps: creating a transaction descriptor and creating the transaction itself.

Creating the Descriptor⚓︎

    // Build the transaction
    const typedDescriptor =
        new descriptors.TransferTransactionV1Descriptor(
            facade.network.publicKeyToAddress(signerKeyPair.publicKey),
            [
                new descriptors.UnresolvedMosaicDescriptor(
                    new models.UnresolvedMosaicId(
                        generateMosaicAliasId('symbol.xym')),
                    new models.Amount(1_000_000n) // 1 XYM
                )
            ]
        );

Typed descriptors are what provide type safety when building transactions in JavaScript, because of their constructors with structured parameters.

See for example the TransferTransactionV1Descriptor used in the code.

Whenever one such descriptor is available, tutorials will link to both the relevant reference page and this guide.

Creating the Transaction⚓︎

    const transaction = facade.createTransactionFromTypedDescriptor(
        typedDescriptor, signerKeyPair.publicKey, 0, 2 * 60 * 60);
    transaction.fee = new models.Amount(feeMult * transaction.size);

Once the descriptor is ready, creating the transaction is straightforward: it simply involves passing the descriptor to the SymbolFacade.createTransactionFromTypedDescriptor method and provide the desired fees and deadline.

Note that, as in the Creating a Transfer Transaction tutorial, the transaction's fee must be calculated after construction because it depends on the transaction's size.

Deadlines are provided differently in the typed and untyped versions

Deadlines passed to SymbolTransactionFactory.create are specified in milliseconds and are relative to the network time. In contrast, deadlines passed to SymbolFacade.createTransactionFromTypedDescriptor are specified in seconds and are relative to the system time, that is, the local clock of the machine running the code.

This approach is convenient because it removes the need to fetch the current network time: for example, to make a transaction expire in two hours, you only need to provide a deadline of 2 * 60 * 60 seconds as in the code above.

However, if the system clock is not properly synchronized with the network time, transactions may expire earlier than expected, or be rejected entirely if the provided deadline exceeds the network's maximum allowed offset of 2 hours.

Therefore, applications using the type-safe method should periodically check the network time to ensure the system clock is properly synchronized.

Once the transaction has been created, you can use it normally. There is no difference between transactions created using the typed and untyped methods.