sotez
    TypeScript icon, indicating that this package has built-in type declarations

    10.0.0 • Public • Published

    Logo

    Sotez

    A JavaScript Library for Tezos

    npm Build Status

    Table of Contents

    Documentation

    More detailed documentation can be found on the wiki Documentation.

    Node Version

    Prerequisites: Node.js (>=8.0.0) or a modern web browser

    Sotez is an isomorphic JavaScript library that can be used seamslessly across both the server and client environments.

    Getting Started

    Installation

    You can install Sotez using npm:

    npm install sotez

    Usage

    Initialize

    Import Sotez and initialize a new instance:

    import { Sotez } from 'sotez';
    
    const tezos = new Sotez('https://testnet-tezos.giganode.io');

    Sotez can be initialized with the following arguments:

    const tezos = new Sotez(provider, chain, moduleOptions);
    • provider: The address of the rpc server of the Tezos node
    • chain: The chain to query (Either 'main' or 'test')
    • moduleOptions: The configurable options to set for an initialized instance
      • defaultFee: The default fee to apply to transactions
      • localForge: Forge operations locally, without an rpc server
      • validateLocalForge: Forge operations locally, but verify against the rpc server
      • debugMode: Sets debug mode
      • useMutez: Use mutez values when referring to balance or amounts

    For example, you can provide additional options when initializing a new instance:

    // New instance initialized with default values
    const tezos = new Sotez('https://testnet-tezos.giganode.io', 'main', {
      defaultFee: 1420,
      localForge: true,
      validateLocalForge: false,
      debugMode: false,
      useMutez: true,
    });

    Query

    After we have initialized an instance of Sotez, we can start querying the blockchain:

    // Get the current head or the latest block
    const head = await tezos.getHead();
    
    // Get the current balance of a Tezos address
    const balance = await tezos.getBalance('tz1e148HC7RUtCcZRNb4UnjNoRjyyxB8pNps');
    
    // Query the RPC directly
    const previousBalance = await tezos.query('/chains/main/blocks/head~30/context/contracts/tz1e148HC7RUtCcZRNb4UnjNoRjyyxB8pNps/balance');

    Sign

    In-memory Key

    In order to perform any actions that require a signature (transfer, delegate, originate, etc.) we need to import a secret key:

    await tezos.importKey('edsk3Z2t7t1XimympW62RmUDQeBxn9dw3pQdxxhpAGngmkjiFuXUAj');

    If you need to import an encrypted key, you can also provide a passphrase as the second argument to the importKey method:

    await tezos.importKey(
      'edesk1RK4W4Qdo6tUwf5oB1swQMXnxJwPo6vWDmWNJEQUbsfA4auJiXdWkXk3JWyzNPAugcQaQuoui1hpNfWfYtK',
      'password',
    );
    Ledger

    You may instead decide that you would like to sign operations using a Ledger device. In that case, you will need to also install the required Transport for the environment you are importing from:

    npm install @ledgerhq/hw-transport-node-hid
    npm install @ledgerhq/hw-transport-webusb
    npm install @ledgerhq/hw-transport-u2f

    Importing a ledger requires that you have the Tezos ledger wallet app installed and the app open on the ledger. The Transport argument is the only required argument, but you can define the BIP44 path as the second argument, and the curve (tz1, tz2, tz3) as the third. If the BIP44 path is not provided, it will use the zero index value ("44'/1729'/0'/0'").

    // Import the required transport for the appropriate environment
    import TransportNodeHid from '@ledgerhq/hw-transport-node-hid';
    
    const tezos = new Sotez('https://testnet-tezos.giganode.io');
    
    await tezos.importLedger(TransportNodeHid, "44'/1729'/0'/0'");

    If using the require syntax, the transport should be defined as such:

    // Import the required transport for the appropriate environment
    const TransportNodeHid = require('@ledgerhq/hw-transport-node-hid').default;
    
    const tezos = new Sotez('https://testnet-tezos.giganode.io');
    
    await tezos.importLedger(TransportNodeHid, "44'/1729'/0'/0'");

    Examples

    Create a transfer operation
    import { Sotez } from 'sotez';
    
    const tezos = new Sotez('https://testnet-tezos.giganode.io');
    
    const transfer = async () => {
      await tezos.importKey(
        'edsk3Z2t7t1XimympW62RmUDQeBxn9dw3pQdxxhpAGngmkjiFuXUAj',
      );
      const { hash } = await tezos.transfer({
        to: 'tz1e148HC7RUtCcZRNb4UnjNoRjyyxB8pNps',
        amount: 1,
      });
    
      console.log(`Waiting for operation ${hash}`);
      const blockHash = await tezos.awaitOperation(hash);
      console.log(`Operation found in block ${blockHash}`);
    };
    
    transfer();
    Set a new delegate
    import { Sotez } from 'sotez';
    
    const tezos = new Sotez('https://testnet-tezos.giganode.io');
    
    const delegate = async () => {
      await tezos.importKey(
        'edsk3Z2t7t1XimympW62RmUDQeBxn9dw3pQdxxhpAGngmkjiFuXUAj',
      );
      const { hash } = await tezos.setDelegate({
        delegate: 'tz1e148HC7RUtCcZRNb4UnjNoRjyyxB8pNps',
      });
    
      console.log(`Waiting for operation ${hash}`);
      const blockHash = await tezos.awaitOperation(hash);
      console.log(`Operation found in block ${blockHash}`);
    };
    
    delegate();
    Load and inspect a contract
    import { Sotez } from 'sotez';
    
    const tezos = new Sotez('https://testnet-tezos.giganode.io');
    
    const contract = async () => {
      await tezos.importKey(
        'edsk3Z2t7t1XimympW62RmUDQeBxn9dw3pQdxxhpAGngmkjiFuXUAj',
      );
    
      // Load contract
      const contract = await sotez.loadContract(
        'KT1DE4txbxNbayiLLs1Z8ruyyNZr11wDMUDo',
      );
    
      // Retrieve contract storage
      const storage = await contract.storage();
    
      // List defined contract methods
      const { methods } = contract;
    
      // Get big map keys
      const bigMapKey = ['tz1ctUVPHDnBYUaAHVTVb7LDB4wDjPGweC7u', 0];
      const bigMapValue = await storage.sLedger.get(bigMapKey);
    
      // Send contract operation
      await contract.methods
        .transfer('tz1P1n8LvweoarK3DTPSnAHtiGVRujhvR2vk', 100)
        .send({
          fee: 100000,
          gasLimit: 800000,
          storageLimit: 60000,
        });
    };
    
    contract();
    Inject an operation
    import { Sotez } from 'sotez';
    
    const tezos = new Sotez('https://testnet-tezos.giganode.io');
    
    const send = async () => {
      await tezos.importKey(
        'edsk3Z2t7t1XimympW62RmUDQeBxn9dw3pQdxxhpAGngmkjiFuXUAj',
      );
      const operation = {
        kind: 'transaction',
        fee: 1420,
        gas_limit: 10600,
        storage_limit: 300,
        amount: 1000,
        destination: 'tz1RvhdZ5pcjD19vCCK9PgZpnmErTba3dsBs',
      };
    
      const { hash } = await sotez.sendOperation({ operation });
    
      console.log(`Waiting for operation ${hash}`);
      const blockHash = await tezos.awaitOperation(hash);
      console.log(`Operation found in block ${blockHash}`);
    };
    
    send();
    Inject a batch operation
    import { Sotez } from 'sotez';
    
    const tezos = new Sotez('https://testnet-tezos.giganode.io');
    
    const send = async () => {
      await tezos.importKey(
        'edsk3Z2t7t1XimympW62RmUDQeBxn9dw3pQdxxhpAGngmkjiFuXUAj',
      );
    
      // Define multiple operation objects
      const operations = [
        {
          kind: 'transaction',
          fee: 1420,
          gas_limit: 10600,
          storage_limit: 300,
          amount: 1000,
          destination: 'tz1RvhdZ5pcjD19vCCK9PgZpnmErTba3dsBs',
        },
        {
          kind: 'transaction',
          fee: 1420,
          gas_limit: 10600,
          storage_limit: 300,
          amount: 1000,
          destination: 'tz1RvhdZ5pcjD19vCCK9PgZpnmErTba3dsBs',
        },
      ];
    
      const { hash } = await sotez.sendOperation({ operation: operations });
    
      console.log(`Waiting for operation ${hash}`);
      const blockHash = await tezos.awaitOperation(hash);
      console.log(`Operation found in block ${blockHash}`);
    };
    
    send();
    Activate a faucet account
    import { Sotez, cryptoUtils } from 'sotez';
    
    const tezos = new Sotez('https://testnet-tezos.giganode.io');
    
    const accountJSON = {
      mnemonic: [
        'raw',
        'peace',
        'visual',
        'boil',
        'prefer',
        'rebel',
        'anchor',
        'right',
        'elegant',
        'side',
        'gossip',
        'enroll',
        'force',
        'salmon',
        'between',
      ],
      secret: '0c5fa9a3d707acc816d23940efdef01aa071bdc6',
      amount: '12358548903',
      pkh: 'tz1eQV2GqDTY7dTucnjzNgvB5nP4H5c7Xr5m',
      password: 'wc0W7jn3Vf',
      email: 'gfjilgzu.trfhzzzk@tezos.example.org',
    };
    
    const activate = async () => {
      const keys = await cryptoUtils.generateKeys(
        accountJSON.mnemonic.join(' '),
        `${accountJSON.email}${accountJSON.password}`,
      );
    
      const { hash } = await tezos.activate(accountJSON.pkh, accountJSON.secret);
    
      console.log(`Waiting for operation ${hash}`);
      const blockHash = await tezos.awaitOperation(hash);
      console.log(`Operation found in block ${blockHash}`);
    };
    
    activate();

    Additional Modules

    cryptoUtils

    This module contains some fundamental crypto utilities that can be used to sign messages, verify messages, extract keys, encrypt keys, validate addresses, or generate new keys.

    extractKeys
    import { cryptoUtils } from 'sotez';
    
    const extract = async () => {
      const extractedKeys = await cryptoUtils.extractKeys(
        'edsk3Z2t7t1XimympW62RmUDQeBxn9dw3pQdxxhpAGngmkjiFuXUAj',
      );
      return extractedKeys;
      // {
      //   sk: string;
      //   pk: string;
      //   pkh: string;
      // }
    };
    
    extract();

    Keys that are encrypted can also be extracted by providing a passphrase as the second argument. Encrypted keys are encrypted with a salt. When extracting encrypted keys, the salt is also provided in order to be able to re-encrypt the secret key to produce the similar salted encrypted key.

    import { cryptoUtils } from 'sotez';
    
    const extract = async () => {
      const extractedKeys = await cryptoUtils.extractKeys(
        'edesk1RK4W4Qdo6tUwf5oB1swQMXnxJwPo6vWDmWNJEQUbsfA4auJiXdWkXk3JWyzNPAugcQaQuoui1hpNfWfYtK',
        'password',
      );
      return extractedKeys;
      // {
      //   sk: string;
      //   esk: string;
      //   pk: string;
      //   pkh: string;
      //   salt: Uint8Array;
      // }
    };
    
    extract();
    generateKeys

    You can generate a new set of keys given a mnemonic and an optional password. NOTE: The passphrase provided to generateKeys is only used to generate the keys and not encrypt them. In order to encrypt the secret key, you need to call encryptSecretKey:

    import { cryptoUtils } from 'sotez';
    
    const generate = async () => {
      // Generate a new random mnemonic
      const mnemonic = cryptoUtils.generateMnemonic();
      // 'raw peace visual boil prefer rebel anchor right elegant side gossip enroll force salmon between'
    
      const keys = await cryptoUtils.generateKeys(mnemonic, 'bip39_seed_password');
      // {
      //   sk: string;
      //   pk: string;
      //   pkh: string;
      // }
    
      const encryptedSecretKey = cryptoUtils.encryptSecretKey(keys.sk, 'password');
    
      return {
        ...keys,
        esk: encryptedSecretKey,
      };
    };
    
    generate();

    Key

    This module is a class representation of the cryptographic functionalities of a Tezos key. When initialized with a secret key or ledger, the basic functions of this class allows the retrieval of the public key, public key hash, secret key, and encrypted secret key. It also can sign messages and verify them against a public key.

    import { Key, magicBytes } from 'sotez';
    
    const setupKey = async () => {
      const key = new Key({
        key:
          'edskRhQtHKMHVf3FDbnqhorMMVXrvgTVNJinVx6WQXb8RVXdKG5PVL5R7JsXU4Sc24wgG5Q5csQBcCQVVd98iSF1QJWjoHLW11',
      });
      await key.ready;
    
      const publicKey = key.publicKey();
      const publicKeyHash = key.publicKeyHash();
      const secretKey = key.secretKey();
      const encryptedSecretKey = key.secretKey('password');
    
      const { bytes, magicBytes, prefixSig } = await key.sign(
        '051d7ba791fbe8ccfb6f83dd9c760db5642358909eede2a915a26275e6880b9a6c02a2dea17733a2ef2685e5511bd3f160fd510fea7db50edd8122997800c0843d016910882a9436c31ce1d51570e21ae277bb8d91b800006c02a2dea17733a2ef2685e5511bd3f160fd510fea7df416de812294cd010000016910882a9436c31ce1d51570e21ae277bb8d91b800ff020000004602000000410320053d036d0743035d0100000024747a31655935417161316b5844466f6965624c3238656d7958466f6e65416f5667317a68031e0743036a0032034f034d031b6c02a2dea17733a2ef2685e5511bd3f160fd510fea7dd016df8122a6ca010000016910882a9436c31ce1d51570e21ae277bb8d91b800ff020000003e02000000390320053d036d0743035d0100000024747a3161575850323337424c774e484a6343443462334475744365766871713254315a390346034e031b6c02a2dea17733a2ef2685e5511bd3f160fd510fea7dc916e08122dec9010000016910882a9436c31ce1d51570e21ae277bb8d91b800ff0200000013020000000e0320053d036d053e035d034e031b',
        magicBytesMap.generic,
      );
    
      const verified = await key.verify(`${magicBytes}${bytes}`, prefixSig);
      // true
    };
    
    setupKey();

    If you want to use a ledger with the Key module, you can initialize the class with a ledger transport. This will only provide the module with the public key. When calling key.sign(...), the ledger will provide the signed data.

    import { Key } from 'sotez';
    import TransportNodeHid from '@ledgerhq/hw-transport-node-hid';
    
    const setupKey = async () => {
      const key = new Key({ ledgerTransport: TransportNodeHid });
      await key.ready;
    };
    
    setupKey();

    You can also load a fundraiser account into the key

    import { Key } from 'sotez';
    
    const FUNDRAISER_ACCOUNT = {
      mnemonic: [
        'spatial',
        'behave',
        'income',
        'advice',
        'guard',
        'isolate',
        'circle',
        'valve',
        'tag',
        'foot',
        'decline',
        'subway',
        'furnace',
        'ancient',
        'output',
      ],
      secret: '8731b6b8cd4b7b67e1e4b76010d8e9f13500ccb5',
      amount: '16474172439',
      pkh: 'tz1UJesXieRG8cZHFUad63RwUfFqh9cwGzvW',
      password: '9zojwTc88E',
      email: 'qvchryer.svikvvex@tezos.example.org',
    };
    
    const setupKey = async () => {
      const key = new Key({
        key: FUNDRAISER_ACCOUNT.mnemonic.join(' '),
        passphrase: FUNDRAISER_ACCOUNT.password,
        email: FUNDRAISER_ACCOUNT.email,
      });
      await key.ready;
    };
    
    setupKey();

    Install

    npm i sotez

    DownloadsWeekly Downloads

    288

    Version

    10.0.0

    License

    MIT

    Unpacked Size

    716 kB

    Total Files

    36

    Last publish

    Collaborators

    • andrewkishino