npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

m10-sdk

v1.0.0

Published

M10 SDK

Downloads

6

Readme

M10-SDK

The M10 Software Development Kit (SDK) provides access to the M10 APIs, enabling you to build custom clients and banking integrations with the M10 Platform.

The M10-SDK is primarily documented using TypeDoc (you can generate the documentation by running yarn run docs) and through examples provided in the tests.

Installing

npm install m10-sdk

API

You can leverage the m10-sdk APIs to query details and metadata for Accounts and Resources, as well as Transactions. Additionally, you can use these APIs to initiate transfers, create documents, and invoke actions.

Getting started

Let's start by defining M10CLient

You use M10CLient to query any data and send transactions in the M10 ecosystem.

import { M10Client } from 'm10-sdk'

const ledgerUrl = "https://app.dev.m10.net";
const m10Client = new M10Client(ledgerUrl);

The preceding code defines a basic client that enables you to query public account details, transactions, and documents. Keep in mind that accessing certain data might necessitate specific permissions.

Within the M10 ecosystem, an Account represents an entry on the M10 ledger and is associated with an Ed25519 public key.

To begin querying data or sending transactions, you need to define a CryptoSigner. This is a utility helper that works with Ed25519 cryptography and the pkcs8 PEM format.

import { CryptoSigner } from 'm10-sdk'

const pkcs8PemKey = "MC4CAQAwBQYDK2VwBCIEIIrikV/M3erX0lqmQgVXDRU1yFLStge7RyyvXv+kDesK"
const aliceSigner = await CryptoSigner.fromPkcs8Pem(pkcs8PemKey)

or with Ed25519 private key

import { CryptoSigner } from 'm10-sdk'

const ed25519PrivateKeyHex = "0x......"
const aliceSigner = await CryptoSigner.fromSeed(
    Buffer.from(ed25519PrivateKeyHex, "hex")
)

With this you can perform a signed operations with M10Client

const aliceClient = new M10Client(ledgerUrl, aliceSigner);

const accountFromBytes = new Uint8Array();
const accountToBytes = new Uint8Array();

const amountToTransfer = 5n;

const decimalPlaces = 2n;

aliceClient.transfer([
    {
        fromAccountId: accountFromBytes,
        toAccountId: accountToBytes,
        amount: amountToTransfer * (10n ** decimalPlaces),
    },
])

To obtain an account, an entity with the necessary permissions must create one for you.

If you are developing an application with a sign-up process:

  1. Generate the user's key pair:
const newUser = CryptoSigner.generateKeyPair()
  1. Transmit the user's public key to your secure server. On this server, an operator or admin account (one with sufficient permissions) can then create a new account and associate it with the user's public key.
const submit = async () => {
    const response = await fetch("https://your-private-server.com/accouns", {
        method: "POST",
        body: JSON.stringify({
            publicKey: aliceSigner.getPublicKey().toString(), // base64
            name: "alice",
        })
    })
}
  1. Submit the request from your private server:
import { Operation_InsertDocument } from "m10-sdk/protobufs/sdk/document";
import { AccountMetadata } from "m10-sdk/protobufs/sdk/model/model";
import { Role, Rule_Verb, RoleBinding } from "m10-sdk/protobufs/sdk/rbac";

import {
    AccountId,
    Collection,
    ResourceId,
    CryptoSigner,
    DirectoryClient,
    getBaseAccessToken,
    M10Client,
} from "m10-sdk";

// assume this in env variables
const operatorKey = 'MC4CA...'

const handleSignUp = async (req, res) => {
    const { publicKey, name } = req.json<{ publicKey: string, name: string }>()

    const operatorClient = new M10Client(
        'https://...',
        await CryptoSigner.fromPkcs8Pem(operatorKey)
    )

    /* Creates account on the ledger */
    const [, accountId] = await operatorClient.createAccount({
        parentId: bankId.bytes,
        frozen: false,
        issuance: true,
    });

    /* Bind public key to newly created account */
    await operatorClient.documents([
        {
            oneofKind: "insertDocument",
            insertDocument: Operation_InsertDocument.create({
                collection: Collection.AccountMetadata,
                document: AccountMetadata.toBinary(
                    AccountMetadata.create({
                        name: name,
                        owner: publicKey,
                        publicName: name,
                        id: accountId.bytes,
                    }),
                ),
            }),
        },
    ]);

    /* Define role and rules for account (permissions) */
    const bankCustomerRole = Role.create({
        id: ResourceId.generate().bytes,
        name: `${name}`,
        rules: [
            {
                collection: Collection.AccountMetadata,
                verbs: [Rule_Verb.CREATE],
            },
            {
                collection: Collection.LedgerAccount,
                verbs: [
                    Rule_Verb.CREATE,
                    ...(additionalLedgerAccRuleVerbs ?? []),
                ],
            },
        ],
    });

    /* send transaction to create document with account's permissions */
    await operatorClient.documents([{
        oneofKind: "insertDocument",
        insertDocument: Operation_InsertDocument.create({
            collection: Collection.Role,
            document: Role.toBinary(bankCustomerRole),
        }),
    }]);

    /* bind those permissions to created account */
    const bankCustomerRoleBinding = RoleBinding.create({
        id: ResourceId.generate().bytes,
        name: `${name}-role-binding`,
        isUniversal: false,
        subjects: [publicKey],
        expressions: [],
        owner: publicKey,
        role: bankCustomerRole.id,
    });

    /* send transaction to create document with role binding */
    await operatorClient.documents([{
        oneofKind: "insertDocument",
        insertDocument: Operation_InsertDocument.create({
            collection: Collection.RoleBinding,
            document: RoleBinding.toBinary(bankCustomerRoleBinding),
        }),
    }]);

    res.ok(204);
}

Upon submission, the user's account will be created on the ledger. In the application you are developing, you can retrieve the details of this newly created account as follows:

import { IndexedAccount } from 'm10-sdk/protobufs/sdk/transaction/transaction'
import { AccountInfo, AccountMetadata } from 'm10-sdk/protobufs/sdk/model/model'

type UserAccount = {
  indexedDetails: IndexedAccount
  account: AccountInfo
  bank: AccountInfo
}

const loadAccounts = async () => {
    const accountListAccounts = await userClient.listAccounts({
        filter: {
            oneofKind: 'owner',
            owner: userSigner.getPublicKey().toUint8Array(),
        },
    })

    return Promise.all(
        accountListAccounts.map(async account => {
            const accountId = AccountId.fromBytes(account.id)

            const [indexedDetails, userAccountInfo] = await Promise.all([
                userClient.getAccount(accountId),
                userClient.getAccountInfo(accountId),
            ])

            const bankInfo = await userClient.getAccountInfo(
                AccountId.fromBytes(userAccountInfo.parentAccountId),
            )

            return {
                indexedDetails,
                account: userAccountInfo,
                bank: bankInfo,
            }
        }),
    )
}

Or you can create a transfer:

const transfer = async (from: AccountId, to: AccountId, amount: bigint) => {
    const txId = await userClient.transfer(
      [
        {
          fromAccountId: from.bytes,
          toAccountId: to.bytes,
          amount: amount,
        },
      ],
    )

    return userClient.getTransfer(txId)
}

Contribution

Protobufs

The M10 SDK communicates with the M10 platform using generated M10 Protocol Buffers (protobufs). To generate the required models, TypeScript types, and API client code from the protobuf definitions, execute the following command:

yarn protoc:ts

Tests

The tests are divided into two categories:

  • tests/integration: This directory provides examples of how to implement specific functionalities.
  • tests/*: These tests are designed to evaluate individual actions in isolation, without any external context.

You can execute all tests using the command yarn test. To generate coverage reports, including an HTML report saved in the coverage folder, use the command yarn test:cover.

Support

If you have any issues with using the SDK, please file an issue on Github.