Signing with our npm package

Figment's npm package named slate simplifies the signing and payload decoding process for networks supported by Figment's API.

This guide covers everything you will need to sign and decode transaction payloads used by Figment's API.

๐Ÿ“˜

Note

The latest version number of the npm package, and how recently it was published, are always available at the top of the page at https://www.npmjs.com/package/@figmentio/slate

Installing the package

npm install @figmentio/slate

Check your package.json dependencies to confirm which version youโ€™re using.

"dependencies": {
    ...
    "@figmentio/slate": "^1.12.0",
    ...
}

Usage

In your code, require @figmentio/slate. The package exports two methods: decode and sign.

const slate = require("@figmentio/slate");

Sign

This method takes five parameters:

  • <network_code> : The name of the network
  • <version> : The Staking API version number used to generate the transaction
  • <transaction_payload> : The raw, unsigned transaction payload returned by the Staking API
  • ["<signing_private_keys>"] : An array of private keys used to sign the transaction payload
  • {<options>} : An object, containing any network-specific options. See the Signing Options section below for details
await slate.sign(
  "near",
  "v1",
  "12000000736c6174652d64656d6f2e746573746e657400415d57cdf21d28e35e0cfa864e895c18b4bc6a711642d38eb6762af81ec1cf3907cc1038fc5700001600000030316e6f64652e706f6f6c2e663836333937332e6d30192fc3497d275b958dea9de8d901c456292125c060c1304318ae9582a7bff20f0100000002110000006465706f7369745f616e645f7374616b65020000007b7d00e057eb481b000000000025a4000a8bca22040000000000",
  ["ed25519:<private_key>"]
);
12000000736c6174652d64656d6f2e746573746e657400415d57cdf21d28e35e0cfa864e895c18b4bc6a711642d38eb6762af81ec1cf3907cc1038fc5700001600000030316e6f64652e706f6f6c2e663836333937332e6d3084edd29289b3a590be582317bb0061016a8df058b7c29a0278f5b82f86c283010100000002080000007769746864726177270000007b22616d6f756e74223a223235303030303030303030303030303030303030303030303030227d00e057eb481b00000000000000000000000000000000000000235397dfd3f0b7ce06a4fe11395e36ce40d12610eae07dcc1dc1d962b38fa9592cdc22f6c9164b0155967a773c369719f71d76b84185ec13c39381343c63cf0b

๐Ÿ“˜

Note

Because the format of private keys differs between networks, attempting to sign a payload with a private key from another network will fail. The private key used to sign the payload must match the delegator's public key or address.

The array of private keys ["<signing_private_keys>"] only requires the private key of the delegator, however it can accommodate multiple private keys in cases where a multisig is used for delegation.

Passing multiple private keys would look like ["<signing_private_key_1>", "<signing_private_key_2>"], etc.

Signing occurs entirely offline; private keys are never exposed during this process.

Refer to the guide Signing Transactions with the Fireblocks API if you require a custodial signing solution.

Signing Options

Cosmos and Polkadot are currently the only networks that require options to be passed when signing with @figmentio/slate.

The options parameter is an optional fifth parameter to the sign method, which only needs to be included when a network requires additional options.

Cosmos

  • accountNumber : This sequential number is generated when an account first receives funds on Cosmos. Account numbers can be determined by querying the Cosmos LCD for account details, or using the Cosmos CLI tool, gaiad.
  • sequence : This sequential number is incremented for each transaction an account has made and is also used to prevent replay attacks. The sequence is commonly referred to as a "nonce" which means "number, used once". Sequence numbers can also be found by querying the Cosmos LCD for account details.
  • chainId : Cosmos chain IDs refer to a specific chain in the Cosmos ecosystem, preventing transactions from one chain being applied to another. You must supply the appropriate chainId when signing a Cosmos transaction.
    • The chainId value for Cosmos mainnet is currently cosmoshub-4
    • The chainId value for Cosmos testnet is currently theta-testnet-001
slate.sign("cosmos", "v1", transaction_payload, ["<signing_private_key>"], {
  accountNumber: "721397",
  sequence: "3",
  chainId: "theta-testnet-001",
});

To view an account's accountNumber and sequence, perform a GET request to the Cosmos LCD endpoint /cosmosโ€‹/authโ€‹/v1beta1โ€‹/accountsโ€‹/{address} with the account address you want to query:

{
  "account": {
    "@type": "/cosmos.auth.v1beta1.BaseAccount",
    "address": "cosmos1nm0rrq86ucezaf8uj35pq9fpwr5r82cl8sc7p5",
    "pub_key": {
      "@type": "/cosmos.crypto.secp256k1.PubKey",
      "key": "ApEvbc+4QJiDoaaXG6v0K3A4zmPON8pu4uzCm4o142u/"
    },
    "account_number": "15652",
    "sequence": "114429"
  }
}

Polkadot

  • rpcUrl โ€” WebSocket URL of the Polkadot RPC endpoint. In most cases, this value should be the public RPC endpoint for the chain you are signing a transaction on. If running your own node, you can specify its RPC endpoint.
    • For Polkadot mainnet, use wss://rpc.polkadot.io
    • For Westend testnet, use wss://westend-rpc.polkadot.io
slate.sign("polkadot", "v1", transaction_payload, ["<signing_private_key>"], {
  rpcUrl: "wss://westend-rpc.polkadot.io",
});

Decode

The decode method takes six parameters:

  • <network_code>: The name of the network (ex. near)
  • <operation>: The operation the transaction is built to accomplish (ex. staking, see below for a complete list)
  • <version>: The Staking API version number used to generate the transaction (ex. v1)
  • <transaction_type>: The type of transaction being decoded (ex. delegateTransaction, see below for a complete list)
  • <transaction_payload>: The raw, unsigned transaction payload returned by the Staking API
  • {<options>}: (optional) An object, containing any network-specific options. See the Decode Options section below for details
await slate.decode(
  "near",
  "staking",
  "v1",
  "delegateTransaction",
  "12000000736c6174652d64656d6f2e746573746e657400415d57cdf21d28e35e0cfa864e895c18b4bc6a711642d38eb6762af81ec1cf3907cc1038fc5700001600000030316e6f64652e706f6f6c2e663836333937332e6d30192fc3497d275b958dea9de8d901c456292125c060c1304318ae9582a7bff20f0100000002110000006465706f7369745f616e645f7374616b65020000007b7d00e057eb481b000000000025a4000a8bca22040000000000"
);
{
  "delegatorPubkey": "5QA46X6NkNmsFdu9xWVBaLNowh9gGeF1c5r9u6NcxaLY",
  "delegatorAddress": "slate-demo.testnet",
  "validatorAddress": "01node.pool.f863973.m0",
  "amount": "5"
}

Decode Options

The options parameter is an optional sixth parameter to the decode method, which only needs to be included when a network requires additional options.

Avalanche

  • hrp โ€” The Human-Readable-Part of the Bech32 encoded address must be passed when decoding Avalanche transaction payloads.
    • For mainnet transactions, the value must be avax
    • For testnet transactions, the value must be fuji
slate.decode(
  "avalanche",
  "staking",
  "v1",
  "delegateTransaction",
  transaction_payload,
  {
    hrp: "fuji",
  }
);

๐Ÿ“˜

Note

There are two less commonly used hrp values: local and custom - however, these are not relevant to Figment's API.

Specifically, the hrp is used by AvalancheJS BinTools.

Read more about Bech32 address encoding in the Avalanche Knowledgebase.

Operations and Transaction Types

These operations are used by the Staking API and the associated transaction types are used when decoding a transaction payload.

NetworkOperationTransaction Type
AvalanchestakingdelegateTransaction
CosmosstakingdelegateTransaction
CosmostransfertransferTransaction
EthereumstakingdepositTransaction
Ethereumaggregated_stakingaggregatedDepositTransaction
NEARstakingdelegateTransaction
NEARunstakingundelegateTransaction
withdrawTransaction
NEARtransfertransferTransaction
PolkadotstakingbondingTransaction
nominationTransaction
PolkadotunstakingchillTransaction
unbondTransaction
withdrawTransaction
PolkadottransfertransferTransaction
Polkadotadd_proxyaddProxyTransaction
Polkadotremove_proxyremoveProxyTransaction
PolygonstakingbondingTransaction
nominationTransaction
Polygonclaim_rewardsclaimRewardsTransaction
SolanastakingcreateStakeAccountTransaction
delegateTransaction
SolanaunstakingdeactivateTransaction
withdrawTransaction
SolanatransfertransferTransaction
Solanasplit_stake_accountsplitStakeAccountTransaction
Solanamerge_stake_accountmergeStakeAccountTransaction

References