Endless
  • 🚀README
  • Discovery
    • 🚀Endless Web3 Genesis Cloud
    • 💎Business Model
    • 🎯Vision
    • ✈️Roadmap
    • 🪙Economics
    • 👤Team
      • Yu Xiong
      • Amit Kumar Jaiswal
      • Ned
      • 0xfun
      • Scott Trowbridge
      • Neeraj Sharma LLB
      • Amjad Suleman
      • Binu Paul
      • Eduard Romulus GOEAN
    • ❤️Developer Community
  • Endless Chain
    • Tech Docs
      • Account Address Format
      • Endless Account
      • Endless Coin(EDS)
      • Sponsored Transaction
      • On-Chain Multisig
      • Randomness
      • Safety Transaction
      • Token Locking & Distribution
    • Start
      • Learn about Endless
        • Accounts
        • Resources
        • Events
        • Transactions and States
        • Gas and Storage Fees
        • Computing Transaction Gas
        • Blocks
        • Staking
          • Delegated Staking
        • Governance
        • Endless Blockchain Deep Dive
          • Validator Nodes Overview
          • Fullnodes Overview
          • Node Networks and Synchronization
        • Move - A Web3 Language and Runtime
      • Explore Endless
      • Latest Endless Releases
      • Networks
    • Build
      • Tutorials
        • Your First Transaction
        • Your First Fungible Asset
        • Your First NFT
        • Your First Move Module
        • Your First Multisig
      • Learn the Move Language
        • The Move Book
          • Getting Started
            • Introduction
            • Modules and Scripts
          • Primitive Types
            • Move Tutorial
            • Integers
            • Bool
            • Address
            • Vector
            • Signer
            • References
            • Tuples and Unit
          • Basic Concepts
            • Local Variables and Scope
            • Equality
            • Abort and Assert
            • Conditionals
            • While, For, and Loop
            • Functions
            • Structs and Resources
            • Constants
            • Generics
            • Abilities
            • Uses and Aliases
            • Friends
            • Packages
            • Package Upgrades
            • Unit Tests
          • Global Storage
            • Global Storage - Structure
            • Global Storage - Operators
          • Reference
            • Libraries
            • Move Coding Conventions
        • Advanced Move Guides
          • Objects
            • Creating Objects
            • Configuring objects
            • Using objects
          • Move Scripts
            • Writing Move Scripts
            • Compiling Move Scripts
            • Running Move Scripts
            • Move Scripts Tutorial
          • Resource Accounts
          • Modules on Endless
          • Cryptography
          • Gas Profiling
          • Security
      • Endless Standards
        • Object
        • Endless Fungible Asset Standard
        • Endless Digital Asset Standard
        • Endless Wallet Standard
      • Endless APIs
        • Fullnode Rest API
        • Indexer Restful API
          • Indexer Installation
        • GRPC Transaction Stream
          • Running Locally
          • Custom Processors
            • End-to-End Tutorial
            • Parsing Transactions
          • Self-Hosted Transaction Stream Service
      • Endless SDKs
        • TypeScript SDK
          • Account
          • SDK Configuration
          • Fetch data from chain
          • Transaction Builder
          • HTTP Client
          • Move Types
          • Testing
          • Typescript
        • Rust SDK
        • Go SDK
      • Endless CLI
        • Install the Endless CLI
          • Install On Mac
          • Install On Alibaba Cloud
          • Install On Linux
          • Install On Windows
        • CLI Configuration
        • Use Endless CLI
          • Working With Move Contracts
            • Arguments in JSON Tutorial
          • Trying Things On-Chain
            • Look Up On-Chain Account Info
            • Create Test Accounts
          • Running A Local Network
            • Running a Public Network
          • Managing a Network Node
      • Integrate with Endless
        • Endless Token Overview
        • Application Integration Guide
      • Endless VSCode extension
      • Advanced Builder Guides
        • Develop Locally
          • Running a Local Network
          • Run a Localnet with Validator
    • Nodes
      • Learn about Nodes
      • Run a Validator and VFN
        • Node Requirements
        • Deploy Nodes
          • Using Docker
          • Using AWS
          • Using Azure
          • Using GCP
        • Connect Nodes
          • Connect to a Network
        • Verify Nodes
          • Node Health
          • Validator Leaderboard
      • Run a Public Fullnode
        • PFN Requirements
        • Deploy a PFN
          • Using Pre-compiled Binary
          • Using Docker
          • Using GCP 🚧 (under_construction)
        • Verify a PFN
        • Modify a PFN
          • Upgrade your PFN
          • Generate a PFN Identity
          • Customize PFN Networks
      • Bootstrap a Node
        • Bootstrap from a Snapshot
        • Bootstrap from a Backup
      • Configure a Node
        • State Synchronization
        • Data Pruning
        • Telemetry
        • Locating Node Files
          • Files For Mainnet
          • Files For Testnet
          • Files For Devnet
      • Monitor a Node
        • Node Inspection Service
        • Important Node Metrics
        • Node Health Checker
    • Reference
      • Endless Error Codes
      • Move Reference Documentation
      • Endless Glossary
    • FAQs
  • Endless Bridge
    • Intro to Endless Bridge
    • How to use bridge
    • Liquidity Management
    • Faucet
    • Developer Integration
      • Contract Integration
        • Message Contract
        • Execute Contract
      • Server-Side Integration
        • Message Sender
        • Example of Message Listener Service (Rust)
        • Example of Token Cross-Chain (JS)
  • Endless Wallet
    • User Guide
    • Basic Tutorial
    • FAQs
    • MultiAccount
    • SDK
      • Functions
      • Events
  • GameFi
    • Intro
    • GameFi & Endless
  • Endless Modules
    • Stacks
    • Storage
    • Module List
  • Endless Ecosystem
    • Intro
    • Show Cases
    • App Demo
  • Whitepaper
  • Endless SCAN
    • User Guide
  • MULTI-SIGNATURE
    • Multi-Signature User Guide
  • Regulations
    • Privacy Policy
    • Terms of Service
    • Funding Terms - Disclaimer
Powered by GitBook
On this page
  • Endless Wallet Standard
  • Mnemonics phrases
  • Creating an Endless account
  • Supporting one mnemonic per multiple account wallets
  • dapp API
  • Connection APIs
  • State APIs
  • Signing APIs
  • Event listening
Export as PDF
  1. Endless Chain
  2. Build
  3. Endless Standards

Endless Wallet Standard

PreviousEndless Digital Asset StandardNextEndless APIs

Last updated 2 months ago

Endless Wallet Standard

The wallet standard provides guidelines for interoperability between wallet types. This ensures dapp developers do not need to change their applications to handle different wallets. This standard offers a single interface for all dapp developers, allowing easy additions of new wallets and more users to each application. This interoperability allows users to choose which wallet they want without worrying about whether apps support their use cases.

In order to ensure interoperability across Endless wallets, the following is required:

  1. Mnemonics - a set of words that can be used to derive account private keys

  2. dapp API - entry points into the wallet to support access to identity managed by the wallet

Mnemonics phrases

A mnemonic phrase is a multiple word phrase that can be used to generate account addresses. However, some wallets may want to support one mnemonic to many accounts coming from other chains. To support both of these use cases, the Endless wallet standard uses a to derive path for mnemonics to accounts.

Creating an Endless account

Endless account creation can be supported across wallets in the following manner:

  1. Generate a mnemonic phrase, for example with BIP39.

  2. Get the master seed from that mnemonic phrase.

  3. Use the BIP44-derived path to retrieve an account address (m/44'/637'/0'/0'/0')

    • See the

    • For example, Endless Wallet always uses the path m/44'/637'/0'/0'/0' since there is one mnemonic per one account.

import { Account, isValidHardenedPath } from '@endlesslab/endless-ts-sdk'
/**
 * Creates new account with bip44 path and mnemonics,
 * @param path. (e.g. m/44'/637'/0'/0'/0')
 * Detailed description: {@link https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki}
 * @param mnemonics.
 * @returns Account
 */
static fromDerivationPath(path: string, mnemonics: string): Account {
  if (!isValidHardenedPath(path)) {
    throw new Error("Invalid derivation path");
  }

  const normalizeMnemonics = mnemonics
    .trim()
    .split(/\s+/)
    .map((part) => part.toLowerCase())
    .join(" ");

  const endlessAccount = Account.fromDerivationPath({
    path: `m/44'/637'/0'/0'/0'`,
    mnemonic: normalizeMnemonics,
  });

  return endlessAccount;
}

Supporting one mnemonic per multiple account wallets

Many wallets from other ecosystems use this paradigm, and take these steps to generate accounts

  1. Generate a mnemonic phrase, for example with BIP39.

  2. Get the master seed from that mnemonic phrase.

  3. Use the BIP44-derived path to retrieve private keys (e.g. m/44'/637'/i'/0'/0') where i is the account index.

  4. Increase i until all the accounts the user wants to import are found.

    • Note: The iteration should be limited, if an account doesn't exist during iteration, keep iterating for a constant address_gap_limit (10 for now) to see if there are any other accounts. If an account is found we will continue to iterate as normal.

ie.

import { EndlessConfig, Network } from '@endlesslab/endless-ts-sdk';

const gapLimit = 10;
let currentGap = 0;

for (let i = 0; currentGap < gapLimit; i += 1) {
  const derivationPath = `m/44'/637'/${i}'/0'/0'`;
  const endlessAccount = fromDerivationPath(derivationPath, mnemonic);
  const endless = new Endless(new EndlessConfig({
    network: Network.TESTNET
  }));

    const response = await endless
    .getAccountResource({
      accountAddress: endlessAccount.accountAddress,
      resourceType: '0x1::account::Account',
    }).catch(error => error);
  if (response.status !== 404) {
    wallet.addAccount(account);
    currentGap = 0;
  } else {
    currentGap += 1;
  }
}

dapp API

More important than account creation, is how wallets connect to dapps. Additionally, following these APIs will allow for the wallet developer to integrate with the Endless Wallet Adapter Standard. The APIs are as follows:

  • connect(), disconnect()

  • getAccount()

  • changeNetwork()

  • getNetwork()

  • signAndSubmitTransaction(data: EndlessSignAndSubmitTransactionInput)

  • signMessage(data: EndlessSignMessageInput)

  • Event listening (EndLessSDKEvent.ACCOUNT_CHANGE, EndLessSDKEvent.SWITCH_NETWORK)

// Common Args and Responses
enum UserResponseStatus {
  APPROVED = 'Approved',
  REJECTED = 'Rejected'
}

interface UserApproval<TResponseArgs> {
  status: UserResponseStatus.APPROVED;
  args: TResponseArgs;
}

interface UserRejection {
  status: UserResponseStatus.REJECTED;
  message?: string;
}

type UserResponse<TResponseArgs> = UserApproval<TResponseArgs> | UserRejection;

type AccountInfo {
    account: AccountAddress;
    address: string;
    authKey: string;
    ansName?: string;
}

type NetworkInfo = {
  name: Network;
  chainId: number;
  url: string;
};

// The important thing to return here is the transaction hash, the dapp can wait for it

// https://github.com/endless-labs/endless-ts-sdk/-/blob/main/src/types/index.ts
type PendingTransactionResponse

// https://www.npmjs.com/package/@endlesslab/endless-web3-sdk/
//      with /src/types.ts
type EndlessSignAndSubmitTransactionInput

// https://github.com/endless-labs/endless-ts-sdk/-/blob/main/src/transactions/types.ts
type InputGenerateTransactionPayloadData

Connection APIs

The connection APIs ensure that wallets don't accept requests until the user acknowledges that they want to see the requests. This keeps the user state clean and prevents the user from unknowingly having prompts.

  • connect() will prompt the user for a connection

    • return Promise<UserResponse<AccountInfo>>

  • disconnect() allows the user to stop giving access to a dapp and also helps the dapp with state management

    • return Promise<void>

State APIs

Get Account

Connection required

Allows a dapp to query for the current connected account address and authkey

  • getAccount() no prompt to the user

    • returns Promise<UserResponse<AccountInfo>>

Get Network

Connection required

Allows a dapp to query for the current connected network name, chain ID, and URL

  • getNetwork() no prompt to the user

    • returns Promise<UserResponse<NetworkInfo>>

Signing APIs

Sign and submit transaction

Connection required

  • signAndSubmitTransaction(data: EndlessSignAndSubmitTransactionInput) will prompt the user with the transaction they are signing

    • returns Promise<UserResponse<{ hash: string }>>

Sign message

Connection required

Allows a dapp to sign a message with their private key. The most common use case is to verify identity, but there are a few other possible use cases. The user should be prompted for approval. You may notice some wallets from other chains just provide an interface to sign arbitrary strings. This can be susceptible to man-in-the-middle attacks, signing string transactions, etc.

Types:

export interface EndlessSignMessageInput {
  address?: boolean;
  application?: boolean;
  chainId?: boolean;
  message: string;
  nonce?: string;
}

export type EndlessSignMessageOutput = {
  address?: string;
  application?: string;
  chainId?: number;
  fullMessage: string;
  publicKey: string;
  message: string;
  nonce: string;
  prefix: 'Endless';
  signature: Signature;
};
  • signMessage(data: EndlessSignMessageInput) prompts the user with the payload.message to be signed

    • returns Promise<SignMessageResponse>

An example: signMessage({message: "Welcome to dapp!"})

This would generate the fullMessage to be signed and returned as the signature:

prefix: Endless
address: 0x000001
application: endless.link
chain_id: 221
nonce: 1234034
message: Welcome to dapp!
publicKey: xxx
fullMessage: xxx
signature: xxx

Event listening

  • Event listening

jssdk.onAccountChange((res) => {
  console.log('ACCOUNT_CHANGE', res);
})
jssdk.onNetworkChange((res) => {
  console.log('NETWORK_CHANGE', res);
})
// or
jssdk.on(EndLessSDKEvent.CONNECT, res => {
  console.log('CONNECT', res);
})
jssdk.on(EndLessSDKEvent.ACCOUNT_CHANGE, res => {
  console.log('ACCOUNT_CHANGE', res);
})
jssdk.on(EndLessSDKEvent.NETWORK_CHANGE, res => {
  console.log('NETWORK_CHANGE', res);
})
jssdk.on(EndLessSDKEvent.DISCONNECT, res => {
  console.log('DISCONNECT', res)
})
jssdk.on(EndLessSDKEvent.OPEN, res => {
  console.log('OPEN', res)
})
jssdk.on(EndLessSDKEvent.CLOSE, res => {
  console.log('CLOSE', res)
})

See the for the derive path

Allows a dapp to send a simple JSON payload using the for signing and submission to the current network. The user should be prompted for approval.

Bitcoin Improvement Proposal (BIP44)
Endless TypeScript SDK's implementation for the derive path
Endless TypeScript SDK's implementation
TypeScript SDK