æternity Documentation Hub
Aeternity.comAeternity GitHub
  • æternity Hub
  • Developer Documentation
  • Aeternity Expansions
    • PULL_REQUEST_TEMPLATE
    • AEX X
    • AEXS
      • AEX 1
      • aex-10
      • AEX 11 Fungible Token Standard
      • AEX-130: æpps Metadata Format Specification
      • aex-141
      • AEX 2
      • AEX-3
      • AEX-4
      • AEX 5
      • AEX 7
      • AEX 8
      • aex-9
    • .github
      • ISSUE_TEMPLATE
        • aexpansion
  • AeMdw - Aeternity Middleware
    • Changelog
    • docs
      • AE MDW Architecture
      • AeMdw Hyperhain Setup Documentation
      • AeMdw Docker Setup Documentation
  • Æternity <> Ethereum Bridge
    • Changelog
  • aepp-cli-js
    • CHANGELOG
    • Contributor guide
    • reference
    • user-guide
    • .github
      • ISSUE_TEMPLATE
  • Hyperchain Bridge
    • Changelog
  • æternity's JavaScript SDK
    • Installation
      • Changelog
      • Compatibility Table
      • Quick Start
      • Transaction options
      • Development
        • Releases
      • guides
        • The range of possible address length
        • AENS (æternity naming system)
        • Batch Transactions
        • How to build a wallet
        • Connect an æpp to a wallet
        • Contract Events
        • Contracts
        • Error Handling
        • JWT usage
        • Ledger Hardware Wallet
        • Low vs High level API
        • Aeternity snap for MetaMask
        • Oracles
        • PayingForTx (Meta-Transactions)
        • Typed data hashing and signing
        • Usage with TypeScript
        • migration
          • Migration to 10.0.0
          • Migration to 11.0.0
          • Migration to 12.0.0
          • Migration to 13.0.0
          • Migration to 14.0.0
          • Migration to 7.0.0
          • Migration to 9.0.0
      • tutorials
        • vuejs
          • Vue.js HelloWorld
    • Examples
      • How to connect wallet to æpp using æternity's JS SDK
        • Sample æpp for contracts
        • iframe-based wallet
        • WebExtension-based wallet
    • .github
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
  • AEproject
    • Changelog
    • docs
      • Quick Start
      • AEproject Library
      • Migration from 3.x.x to 4.x.x
      • Migration from 4.x.x to 5.x.x
      • Upcoming Version Support
      • cli
        • Local Environment
        • Project Initialization
        • Unit Testing
    • .github
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
  • aerepl
    • Changelog
  • aescan
    • Changelog
    • Contributor Covenant Code of Conduct
    • Aescan Contributing Guide
    • LICENSE
    • .github
      • pull_request_template
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
    • docs
      • BRANCHING_STRATEGY
  • Sophia Support for Visual Studio Code
    • Changelog
  • aesophia
    • Changelog
    • Contributing to Sophia
    • docs
      • aeso_aci
      • aeso_compiler
      • Introduction
      • sophia
      • Contract examples
      • Features
      • Standard library
      • Syntax
  • aesophia_cli
    • Changelog
  • aesophia_http
    • Changelog
  • Æ Studio - Formerly known as 🔥 Fire Editor ! Aeternity's easy to use editor for writing smart contr
    • ideas
  • aeternity
    • .github
      • The Æternity Code of Conduct
      • Contributing to the Aeternity node
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
    • Welcome to Aeternity node documentation
      • Summary
      • Node API
      • Introduction
      • Build from source
      • Configuration
      • CUDA Miner
      • debian_ubuntu_packaging
      • Docker
      • Fork resistance in Aeternity nodes
      • Garbage Collection
      • Hacking the Aeternity Codebase
      • Hardware Requirements
      • hyperchains
      • Installation
      • Network Monitoring
      • Operation
      • Rebar Quick Guide
      • Stratum
      • Testing
      • Update
      • release-notes
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • next-ceres
          • GH-3706-micro_block_gas_limit_used_gas
          • GH-4009-allow_contract_call_by_name
          • GH-4056-add_raw_data_pointers_to_AENS
          • GH-4080-wildcard_aens_delegation_signature
          • GH3417-tamper_protection_on_ga_meta_tx
          • aega_only_allow_attach_for_fresh_accounts
          • aens_auction_adjustments
          • aens_preclaim_optional
          • deprecate_swagger
          • fate_extensions
        • next
          • GH-3088-db_direct_access-as-default
          • GH-4087_http_endpoint_info_inner_txs
          • GH4157-control-mempool-sync-start
    • Emergency patching of OTP modules
    • rosetta
    • apps
      • aehttp
        • priv
          • rosetta_README
    • data
      • aecore
        • Token migration contract
  • Hyperchains whitepaper
    • Hyperchains: Bridging Security and Scalability Through Periodic Synchronization
    • LICENSE
    • Periodically-Syncing-HyperChains
    • generations
    • Glossary
    • Hyperchain Properties
    • staking
  • æternity protocol
    • æternity naming system
    • Gossip
    • Stratum
    • SYNC
    • Serialization formats
    • State Channels
      • Off-chain
      • On-chain
      • Authentication
      • Channel off-chain state
    • æternity consensus protocol
      • Bitcoin-NG for æternity
      • Coinbase at height
      • consensus
      • Coins locking
    • Smart Contracts
      • The æternity Ethereum virtual machine (AEVM)
      • contract_state_tree
      • Contract Transactions
      • Virtual machines on the æternity blockchain
      • contracts
      • Events
      • fate
      • The Solidity Language
      • sophia
      • sophia_stdlib
    • Generalized accounts
      • Generalized accounts - explained
      • generalized_accounts
    • Oracles
      • Oracle life cycle examples
      • Oracle state tree
      • Oracle transactions
      • oracles
    • Sync
      • P2P messages
      • Mempool/TX-pool synchronization
    • node
      • æternity node API
        • Account management - intended usage
        • Encoding scheme for API identifiers and byte arrays
        • State channel WebSocket API
        • Channels - intended usage
        • Contracts - intended usage
        • Mining - intended usage
        • Naming System - intended usage
        • Oracles - intended usage
        • Spending coins - intended usage
        • examples
          • æternity node channel WebSocket API examples
            • json-rpc
              • sc_ws_basic_open_close
              • sc_ws_basic_open_close_server
              • sc_ws_broken_open_params
              • sc_ws_close_mutual
              • sc_ws_close_solo
              • sc_ws_leave_reconnect
              • sc_ws_leave_reestablish
              • sc_ws_leave_reestablish_responder_stays
              • sc_ws_leave_reestablish_wrong_fsm_id
              • sc_ws_min_depth_is_modifiable
              • sc_ws_min_depth_not_reached_timeout
              • sc_ws_opening_ping_pong
              • sc_ws_reconnect_early
              • sc_ws_slash
              • sc_ws_snapshot_solo
              • sc_ws_timeout_open
              • sc_ws_update_with_meta
              • abort_updates
                • sc_ws_abort_deposit
                • sc_ws_abort_offchain_update
                • sc_ws_abort_settle
                • sc_ws_abort_shutdown
                • sc_ws_abort_slash
                • sc_ws_abort_snapshot_solo
                • sc_ws_abort_withdraw
                • sc_ws_can_not_abort_while_open
              • assume_min_depth
                • sc_ws_basic_open_close
              • both_sign
                • init_per_group
                • conflicts
                  • sc_ws_conflict_deposit_and_offchain_update
                  • sc_ws_conflict_two_deposits
                  • sc_ws_conflict_two_offchain_updates
                  • sc_ws_conflict_two_withdrawals
                  • sc_ws_conflict_withdrawal_and_deposit
                  • sc_ws_conflict_withdrawal_and_offchain_update
              • changeable_fee
                • sc_ws_optional_params_close_solo
                • sc_ws_optional_params_create
                • sc_ws_optional_params_deposit
                • sc_ws_optional_params_settle
                • sc_ws_optional_params_slash
                • sc_ws_optional_params_snapshot
                • sc_ws_optional_params_withdrawal
                • sc_ws_set_fee_close_mutual
                • sc_ws_set_fee_close_solo
                • sc_ws_set_fee_create
                • sc_ws_set_fee_deposit
                • sc_ws_set_fee_settle
                • sc_ws_set_fee_slash
                • sc_ws_set_fee_snapshot
                • sc_ws_set_fee_withdrawal
              • changeable_fee_higher_than_gas_price
                • sc_ws_optional_params_close_solo
                • sc_ws_optional_params_create
                • sc_ws_optional_params_deposit
                • sc_ws_optional_params_settle
                • sc_ws_optional_params_slash
                • sc_ws_optional_params_snapshot
                • sc_ws_optional_params_withdrawal
              • changeable_fee_lower_than_gas_price
                • sc_ws_optional_params_close_solo
                • sc_ws_optional_params_create
                • sc_ws_optional_params_deposit
                • sc_ws_optional_params_settle
                • sc_ws_optional_params_slash
                • sc_ws_optional_params_snapshot
                • sc_ws_optional_params_withdrawal
              • changeable_gas_price
                • sc_ws_optional_params_close_solo
                • sc_ws_optional_params_create
                • sc_ws_optional_params_deposit
                • sc_ws_optional_params_settle
                • sc_ws_optional_params_slash
                • sc_ws_optional_params_snapshot
                • sc_ws_optional_params_withdrawal
              • changeable_nonce
                • sc_ws_optional_params_fail_close_mutual
                • sc_ws_optional_params_fail_close_solo
                • sc_ws_optional_params_fail_create
                • sc_ws_optional_params_fail_deposit
                • sc_ws_optional_params_fail_force_progress
                • sc_ws_optional_params_fail_settle
                • sc_ws_optional_params_fail_slash
                • sc_ws_optional_params_fail_snapshot
                • sc_ws_optional_params_fail_withdrawal
              • continuous
                • init_per_group
                • sc_ws_deposit
                • sc_ws_failed_update
                • sc_ws_generic_messages
                • sc_ws_ping_pong
                • sc_ws_update_conflict
                • sc_ws_withdraw
              • contracts
                • init_per_group
                • sc_ws_basic_contracts
                • sc_ws_environment_contract
                • sc_ws_nameservice_contract
                • sc_ws_oracle_contract
                • sc_ws_remote_call_contract
                • sc_ws_remote_call_contract_refering_onchain_data
                • sc_ws_wrong_call_data
              • force_progress
                • sc_ws_force_progress_based_on_offchain_state
                • sc_ws_force_progress_based_on_onchain_state
              • only_one_signs
                • init_per_group
                • sc_ws_conflict_on_new_offchain
                • sc_ws_conflict_snapshot_and_offchain_update
                • conflicts
                  • sc_ws_conflict_deposit_and_offchain_update
                  • sc_ws_conflict_two_deposits
                  • sc_ws_conflict_two_offchain_updates
                  • sc_ws_conflict_two_withdrawals
                  • sc_ws_conflict_withdrawal_and_deposit
                  • sc_ws_conflict_withdrawal_and_offchain_update
              • reconnect
                • sc_ws_basic_client_reconnect_i
                • sc_ws_basic_client_reconnect_i_w_reestablish
                • sc_ws_basic_client_reconnect_r
              • with_meta
                • init_per_group
                • sc_ws_deposit
                • sc_ws_remote_call_contract
                • sc_ws_withdraw
              • generalized_accounts
                • both
                  • sc_ws_basic_open_close
                • initiator
                  • sc_ws_basic_open_close
                • responder
                  • sc_ws_basic_open_close
  • Superhero Wallet
    • Changelog
    • Contributing & Guidelines
    • docs
      • Deep link URL Schema
    • .github
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
  • aerepl-web-bridge
    • AereplApi
    • aerepl_components
Powered by GitBook
On this page
  • Extract types of methods exposed by SDK
  • Initialize parameters with specific types
  • Narrow the union type returned by unpackTx, unpackDelegation, and unpackEntry
  • Functions to assert types of user-provided data
  • AENS name validation
  • Check types of contract methods

Was this helpful?

Export as PDF
  1. æternity's JavaScript SDK
  2. Installation
  3. guides

Usage with TypeScript

PreviousTyped data hashing and signingNextmigration

Last updated 1 month ago

Was this helpful?

This guide explains handling the edge cases that can occur while using aeternity SDK in a TypeScript project.

Firstly, ensure you've set up TypeScript according to the .

Extract types of methods exposed by SDK

SDK doesn't expose types separately to reduce the number of exports and simplify tracking of breaking changes. But you may need these types to prepare parameters or to hold the return value. In such cases, it is advised to use TypeScript-provided generics and . For example,

import { walletDetector } from '@aeternity/aepp-sdk';

type WDCallback = Parameters<typeof walletDetector>[1];
type Wallet = Parameters<WDCallback>[0]['newWallet'];
let wallet: Wallet | null = null;

const stop = walletDetector(connection, ({ newWallet }) => {
  wallet = newWallet;
  stop();
});

The same for :

import { unpackDelegation } from '@aeternity/aepp-sdk';

type DlgUnpacked = ReturnType<typeof unpackDelegation>;
let delegation: DlgUnpacked | null = null;

delegation = unpackDelegation(
  'ba_+EYDAaEBXXFtZp9YqbY4KdW8Nolf9Hjp0VZcNWnQOKjgCb8Br9mhBV1xbWafWKm2OCnVvDaJX/R46dFWXDVp0Dio4Am/Aa/Z2vgCEQ==',
);

Initialize parameters with specific types

You may need to define an object with parameters to call an sdk method. Obvious to try it as

import { packEntry, EntryTag } from '@aeternity/aepp-sdk';

const gaAuthData = {
  tag: EntryTag.GaMetaTxAuthData,
  fee: 766e11,
  txHash: 'th_2CKnN6EorvNiwwqRjSzXLrPLiHmcwo4Ny22dwCrSYRoD6MVGK1',
};

const gaAuthDataPacked = packEntry(gaAuthData);
import { Tag, Encoded } from '@aeternity/aepp-sdk';

interface GaAuthData {
  tag: Tag;
  fee: number;
  txHash: Encoded.TxHash;
}

const gaAuthData: GaAuthData = {
  tag: EntryTag.GaMetaTxAuthData,
  fee: 766e11,
  txHash: 'th_2CKnN6EorvNiwwqRjSzXLrPLiHmcwo4Ny22dwCrSYRoD6MVGK1',
};

Or to define gaAuthData as immutable:

const gaAuthData = {
  tag: EntryTag.GaMetaTxAuthData,
  fee: 766e11,
  txHash: 'th_2CKnN6EorvNiwwqRjSzXLrPLiHmcwo4Ny22dwCrSYRoD6MVGK1',
} as const;
import { unpackTx, Tag } from '@aeternity/aepp-sdk';

const encodedTx =
  'tx_+F0MAaEB4TK48d23oE5jt/qWR5pUu8UlpTGn8bwM5JISGQMGf7ChAeEyuPHdt6BOY7f6lkeaVLvFJaUxp/G8DOSSEhkDBn+wiBvBbWdOyAAAhg9e1n8oAAABhHRlc3QLK3OW';

const tx = unpackTx(encodedTx);

if (tx.tag !== Tag.SpendTx) {
  throw new Error(`Unknown transaction type: ${Tag[tx.tag]}`);
}

console.log(tx.amount);

Without checking the tx.tag TypeScript will fail with

Property 'amount' does not exist on type 'TxUnpackedSignedTx1 & { tag: Tag; }'.

const tx = unpackTx(encodedTx, Tag.SpendTx);

But if you need to get SpendTx properties inside a SignedTx you still need to use the above tag check.

const tx = unpackTx<Tag.SpendTx>(encodedTx);

The problem is that JavaScript won't check if the transaction is a SpendTx, so provide Tag.SpendTx as the second argument instead (as the above).

Functions to assert types of user-provided data

await aeSdk.spend(100, address as Encoded.AccountAddress);
import { isEncoded, Encoding } from '@aeternity/aepp-sdk';

if (!isEncoded(address, Encoding.AccountAddress)) {
  alert('The address is not valid');
  return;
}

await aeSdk.spend(100, address);
import { Encoding } from '@aeternity/aepp-sdk';

isEncoded(address, Encoding.ContractAddress, Encoding.OracleAddress);

Or encoding types in general:

isEncoded(address, Encoding.Transaction);

AENS name validation

import { isName } from '@aeternity/aepp-sdk';

console.log(isName('name.chain')); // true
console.log(isName('мир.chain')); // true
console.log(isName('🙂.chain')); // false
import { ensureName, Name } from '@aeternity/aepp-sdk';

const nameAsString: string = readName();
ensureName(nameAsString);
const name = new Name(nameAsString, options);

Check types of contract methods

import { Contract } from '@aeternity/aepp-sdk';

const sourceCode = `
include "String.aes"

contract Test =
  entrypoint foo(x: int) = x

  entrypoint bar(x: map(string, int)) = x

  datatype name = FirstName(string) | LastName(string)
  entrypoint baz(n: name) =
    switch(n)
      FirstName(first) => String.length(first)
      LastName(_) => abort("Last name not supported yet")
`;

const contract = await Contract.initialize<{
  foo: (v: bigint) => bigint;
  bar: (x: Map<string, bigint>) => Map<string, bigint>;
  baz: (v: { FirstName: [string] } | { LastName: [string] }) => number;
}>({
  ...aeSdk.getContext(),
  sourceCode,
});

await contract.$deploy([]);

console.log((await contract.foo(21n)).decodedResult); // 42
console.log((await contract.bar(new Map([['test', 10n]]))).decodedResult); // Map(1) { 'test' => 10n }
console.log((await contract.baz({ FirstName: ['Nikita'] })).decodedResult); // 6
import { ContractMethodsBase } from '@aeternity/aepp-sdk';

interface FooContract extends ContractMethodsBase {
  foo: (v: bigint) => bigint;
  bar: (x: Map<string, bigint>) => Map<string, bigint>;
  baz: (v: { FirstName: [string] } | { LastName: [string] }) => number;
}

const contract = await Contract.initialize<FooContract>({
  ...aeSdk.getContext(),
  sourceCode,
});

The problem in this case, is that TypeScript will generalize the type of unpackedEntry.txHash to string instead of th_${string} making it incompatible with arguments of . To fix this you may define gaAuthData's type explicitly, like:

In the last case, txHash's type will be exactly "th_2CKnN6EorvNiwwqRjSzXLrPLiHmcwo4Ny22dwCrSYRoD6MVGK1", making it compatible with .

Narrow the union type returned by , , and

Some sdk methods return a of multiple types. For example, returns a union of fields. To work correctly you need to narrow this type to a specific transaction before accessing its fields. For example,

The above check is also implemented in itself, instead of checking the tx.tag you can provide Tag in the second argument:

You may find that is a generic function so that it can be executed as

Let's assume we need to receive an address from the user to send some coins to it. The user enters an address in a text box, we can get it as a string. method accepts the address as , it won't accept a general string. We can overcome this restriction by adding a type assertion, like:

The problem is that TypeScript won't check if address is an ak_-encoded string, and the method will fail in this case. A more accurate solution would be to check the address in advance, providing user feedback if it is incorrect. For example:

Please note that this method doesn't require explicit casting string to because implicitly marks address as ak_${string} in case it returns true.

Additionally, you can use to validate data against other address types:

The similar way can be used

If you don't need to handle invalid names specially then you can use :

Doing this way, will throw an exception if nameAsString is not a proper AENS name. TypeScript will handle nameAsString as ${string}.chain in lines below invocation.

By default, it is allowed to call any method of the instance. You can enable type-checking by providing a contract interface in a generic parameter of . For example:

If you need to define the contract interface separately then extend :

It is theoretically possible to generate a contract interface by ACI. But unfortunately, it is currently.

packEntry
packEntry
unpackTx
unpackDelegation
unpackEntry
union
unpackTx
all supported transaction
unpackTx
unpackTx
spend
Encoded.AccountAddress
spend
Encoded.AccountAddress
isEncoded
isEncoded
isName
ensureName
ensureName
ensureName
Contract
Contract
ContractMethodsBase
not supported
Parameters
ReturnType
ReturnType
installation guide