Skip to content

Raw signer

PAPI provides a helper to build a PolkadotSigner instance directly from a raw signing function, provided by a cryptographic library, a hardware wallet, etc. It just deals with the chain logic side and leaves to the consumer the cryptographic signature part.

getPolkadotSigner

It is a function to get a signer.

Returns

PolkadotSigner

Parameters

publicKey

Type: Uint8Array

publicKey used to identify the signer.

signingType

Type: "Ecdsa" | "Ed25519" | "Sr25519"

Signature schema used to sign.

sign

Type: (input: Uint8Array) => Promise<Uint8Array> | Uint8Array

Cryptographic signature function, signing with the signingType previously declared.

Examples

In these examples we use several libraries:

Some snippets might work in other versions.

Ed25519

import { getPolkadotSigner } from "polkadot-api/signer"
import { ed25519 } from "@noble/curves/ed25519.js"
 
const SECRET_KEY = new Uint8Array() // get your key
 
const signer = getPolkadotSigner(
  ed25519.getPublicKey(SECRET_KEY),
  "Ed25519",
  (i) => ed25519.sign(i, SECRET_KEY),
)

Sr25519

From private key

import { getPolkadotSigner } from "polkadot-api/signer"
import * as sr25519 from "@scure/sr25519"
 
const SECRET_KEY = new Uint8Array() // get your key
 
const signer = getPolkadotSigner(
  sr25519.getPublicKey(SECRET_KEY),
  "Sr25519",
  (i) => sr25519.sign(SECRET_KEY, i),
)

From mnemonic phrase

This snippet helps to create a signer for Alice, Bob, Charlie, etc.

You can replace by your own mnemonic phrase.

import { sr25519CreateDerive } from "@polkadot-labs/hdkd"
import {
  DEV_PHRASE,
  entropyToMiniSecret,
  mnemonicToEntropy,
} from "@polkadot-labs/hdkd-helpers"
import { getPolkadotSigner } from "polkadot-api/signer"
 
const miniSecret = entropyToMiniSecret(mnemonicToEntropy(DEV_PHRASE))
const derive = sr25519CreateDerive(miniSecret)
const hdkdKeyPair = derive("//Alice") // or `//Bob`, `//Charlie`, etc
 
const polkadotSigner = getPolkadotSigner(
  hdkdKeyPair.publicKey,
  "Sr25519",
  hdkdKeyPair.sign,
)

Ecdsa

Ecdsa signer is an umbrella term for two types of signers using ECDSA signatures over Secpk1. In a glance, these are the two types:

  • EVM-like chains (Moonbeam, Mythos, Darwinia, Crab, etc.) expect the signer to sign payloads using a Keccak256 hash and use AccountId20 addresses (Ethereum-like addresses).
  • Polkadot-like chains (e.g., Polkadot, Kusama) expect the signer to sign payloads using Blake2_256 and use AccountId32 addresses (Polkadot-like addresses).

With that distinction in mind, here's how you can create Ecdsa PolkadotSigners for these different chain types:

Polkadot-like chains

import { secp256k1 } from "@noble/curves/secp256k1.js"
import { blake2b } from "@noble/hashes/blake2.js"
import { getPolkadotSigner } from "polkadot-api/signer"
 
const SECRET_KEY = new Uint8Array() // get your key
 
const signer = getPolkadotSigner(
  blake2b(secp256k1.getPublicKey(SECRET_KEY), { dkLen: 32 }),
  "Ecdsa",
  (i) => {
    const signature = secp256k1.sign(blake2b(i, { dkLen: 32 }), SECRET_KEY, {
      prehash: false,
      format: "recovered",
    })
    return Uint8Array.from([...signature.slice(1), signature[0]])
  },
)

Ethereum-like chains

import { secp256k1 } from "@noble/curves/secp256k1.js"
import { keccak_256 } from "@noble/hashes/sha3.js"
import { getPolkadotSigner } from "polkadot-api/signer"
 
const SECRET_KEY = new Uint8Array() // get your key
 
const signer = getPolkadotSigner(
  keccak_256(secp256k1.getPublicKey(SECRET_KEY, false).slice(1)).slice(-20),
  "Ecdsa",
  (i) => {
    const signature = secp256k1.sign(keccak_256(i), SECRET_KEY, {
      prehash: false,
      format: "recovered",
    })
    return Uint8Array.from([...signature.slice(1), signature[0]])
  },
)