#### Requesting proof-of-work from an online service
+Instantiating Rpc object with API key included for `Authorization` header
+
```javascript
-const node = new Rpc("https://nano-node.example.com/");
+const node = new Rpc("https://nano-node.example.com/", 'api-key-example-123456789');
try {
await block.pow("https://nano-node.example.com/");
} catch (err) {
#### Processing a block on the network
+Using process environment to set `Authorization` header
+
+```console
+#!/usr/env/bash
+
+export LIBNEMO_RPC_AUTHORIZATION = 'api-key-example-123456789'
+```
+
```javascript
-const node = new Rpc("https://nano-node.example.com", "nodes-api-key");
+const node = new Rpc("https://nano-node.example.com");
try {
const hash = await block.process("https://nano-node.example.com/");
} catch (err) {
# SPDX-License-Identifier: GPL-3.0-or-later
# Save this file as `.env` and replace the following with real values
-NODE_URL="https://rpc.example.com"
-API_KEY_NAME="api_key"
-LIBNEMO_RPC_API_KEY="fedcba9876543210fedcba9876543210"
+LIBNEMO_RPC_URL="https://rpc.example.com"
+LIBNEMO_RPC_AUTHORIZATION="fedcba9876543210fedcba9876543210"
// Save this file as `env.mjs` and replace the following with real values
export const env = {
- NODE_URL: "https://rpc.example.com",
- API_KEY_NAME: "api_key",
- LIBNEMO_RPC_API_KEY: "fedcba9876543210fedcba9876543210"
+ LIBNEMO_RPC_URL: "https://rpc.example.com",
+ LIBNEMO_RPC_AUTHORIZATION: "fedcba9876543210fedcba9876543210"
}
/**
* Represents a Nano network node. It primarily consists of a URL which will
- * accept RPC calls, and an optional API key header construction can be passed if
- * required by the node. Once instantiated, the Rpc object can be used to call
- * any action supported by the Nano protocol. The URL protocol must be HTTPS; any
- * other value will be changed automatically.
+ * accept RPC calls; an optional authentication header name can be passed if an
+ * API key is required by the node. Once instantiated, the Rpc object can be
+ * used to call any action supported by the Nano protocol.
+ *
+ * The URL protocol must be HTTPS; any other protocol will be changed to
+ * `https:` automatically.
*/
export class Rpc {
- #u: URL
- #n?: string
+ #url: URL
+ #auth?: string
/**
- * @param {(string|URL)} url
- * @param {string} [apiKeyName]
+ * @param {(string|URL)} url Nano network node
+ * @param {string} [auth] optional API key
*/
- constructor (url: string | URL, apiKeyName?: string) {
- this.#u = new URL(url)
- this.#u.protocol = 'https:'
- this.#n = apiKeyName
+ constructor (url: string | URL, auth?: string) {
+ this.#url = new URL(url)
+ this.#url.protocol = 'https:'
+ this.#auth = auth
}
/**
async post (action: unknown, data: unknown): Promise<unknown> {
const env = typeof process !== 'undefined' && 'env' in process ? process.env : null
this.#validate(action)
- const headers: Record<string, string> = {}
- headers['Content-Type'] = 'application/json'
- if (this.#n && env?.LIBNEMO_RPC_API_KEY) {
- headers[this.#n] = env.LIBNEMO_RPC_API_KEY
+ const headers: Record<string, string> = {
+ 'Content-Type': 'application/json'
+ }
+ const auth = this.#auth ?? env?.LIBNEMO_RPC_AUTHORIZATION
+ if (auth) {
+ headers['Authorization'] = auth
}
if (data !== undefined && typeof data !== 'object') {
throw new TypeError('Invalid RPC post data')
reqBody.action = action.toLowerCase()
const aborter = new AbortController()
- const req = new Request(this.#u, {
+ const req = new Request(this.#url, {
signal: aborter.signal,
method: 'POST',
headers,
}, 10000)
try {
const res = await fetch(req)
+ const { status, statusText } = res
const resBody = await res.json()
- if (res.status !== 200) {
- throw new Error(`${res.status} ${res.statusText}`, { cause: resBody })
- }
- if (resBody.error != null) {
- const msg = resBody.message == null
- ? resBody.error
- : `${resBody.error} ${resBody.message}`
- throw new Error(msg)
+ const { error, message } = resBody
+ if (status !== 200 || error != null) {
+ throw new Error(`${status} ${statusText}`, { cause: { error, message } })
}
- return resBody
+ return message
} catch (err) {
console.error(err)
throw new Error(`RPC ${action} request failed`, { cause: err })
//! SPDX-License-Identifier: GPL-3.0-or-later
//@ts-nocheck
-export { env } from '../env.mjs'
+import { Rpc } from 'libnemo'
+import { env } from '../env.mjs'
+
+export { env }
+export const isNode = globalThis !== globalThis.window
+export const rpc = new Rpc(env?.LIBNEMO_RPC_URL ?? '', env.LIBNEMO_RPC_AUTHORIZATION)
if (globalThis.sessionStorage == null) {
let _sessionStorage = {}
}
}
-export const isNode = globalThis !== globalThis.window
-
let NodeTestSuite, NodeTestTest
if (isNode) {
({ suite: NodeTestSuite, test: NodeTestTest } = await import('node:test'))
'use strict'
import { Account, Rpc, Wallet } from 'libnemo'
-import { assert, env, suite, test } from './GLOBALS.mjs'
+import { assert, rpc, suite, test } from './GLOBALS.mjs'
import { NANO_TEST_VECTORS, TEST_PASSWORD } from './VECTORS.mjs'
-const rpc = new Rpc(env.NODE_URL ?? '', env.API_KEY_NAME)
-
await Promise.all([
suite('Refreshing account info', { skip: false }, async () => {
+
await test('fetch balance, frontier, and representative', async () => {
const wallet = await Wallet.load('BIP-44', TEST_PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
await wallet.unlock(TEST_PASSWORD)
\r
'use strict'\r
\r
-import { Rpc, Tools, Wallet } from 'libnemo'\r
-import { assert, click, env, suite, test } from './GLOBALS.mjs'\r
+import { Tools, Wallet } from 'libnemo'\r
+import { assert, click, rpc, suite, test } from './GLOBALS.mjs'\r
import { MAX_RAW, MAX_SUPPLY, NANO_TEST_VECTORS, TEST_PASSWORD } from './VECTORS.mjs'\r
\r
-const rpc = new Rpc(env?.NODE_URL ?? '', env?.API_KEY_NAME)\r
-\r
await Promise.all([\r
suite('Tools unit conversion tests', async () => {\r
\r