# Node.js Library - picket-node

### Installation

```shell
npm install "@picketapi/picket-node"
```

### Usage - Quick Start

The Picket constructor creates a new instance of the Picket class. It takes a *secret API key* as a parameter.

```typescript
import Picket from "@picketapi/picket-node";

// Use your secret key when making calls from secure server
const picket = new Picket("YOUR_SECRET_KEY_HERE");
```

We’ve placed a placeholder secret API key in this example. Replace it with your [actual api keys](https://picketapi.com/dashboard).

### Nonce

A `nonce` is random value generated by the Picket API to that user must sign to prove ownership a wallet address. The `nonce` function can be used to implement your own wallet authentication flow.&#x20;

A `nonce` is unique to a project and wallet address. If a `nonce` doesn't exist for the project and wallet address, Picket will generate a new `nonce`; otherwise, Picket will return the existing nonce. A `nonce` is valid for two minutes before self-destructing.

```javascript
const { nonce, statement, locale } = await picket.nonce({ 
    chain: "ethereum",
    walletAddress: "0x_WALLET_ADDRESS" 
});
```

#### Statement Localization

`nonce` takes in an optional `locale` parameter, which is used to localize the signing message statement in to the given `locale` . When using the `login` function from `picket-js` or `picket-react` , the user's browser locale will automatically be passed as the `locale` for the signing message statement.

{% hint style="info" %}
**Language Codes**

`locale` must be a BCP-47 language code. To see a full list, checkout [language subtag registry](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry)
{% endhint %}

```typescript
const { nonce, statement, format } = await picket.nonce({ 
    chain: "ethereum",
    walletAddress: "0x_WALLET_ADDRESS",
    // translate the statement to Afrikaans
    locale: "af",
});
```

### Auth

`auth` is the server-side equivalent of `login`. `auth` should only be used in a trusted server environment. The most common use-case for `auth` is [linking a wallet to an existing application account](/picket-docs/tutorials/link-a-wallet-to-a-web-2.0-account.md).&#x20;

#### Wallet Authentication

{% tabs %}
{% tab title="Ethereum (Mainnet)" %}

```typescript
await picket.auth({
    // optionally omit, the default chain is Ethereum
    walletAddress: "0x_WALLET_ADDRESS",
    signature: "SIGNATURE"
});

// or specifiy it explicitly
await picket.auth({
    chain: "ethereum",
    walletAddress: "0x_WALLET_ADDRESS",
    signature: "SIGNATURE"
});
```

{% endtab %}

{% tab title="Solana" %}

```typescript
await picket.auth({
    chain: "solana",
    walletAddress: "0x_WALLET_ADDRESS",
    signature: "SIGNATURE"
});
```

{% endtab %}
{% endtabs %}

#### Token Gating

{% hint style="info" %}
**Checkout the Getting Started Guides**

For more information on Token Gating, read the [Ethereum](/picket-docs/quick-start-guides/quick-start-guides/token-gating-ethereum-evm.md) or [Solana](/picket-docs/quick-start-guides/quick-start-guides/token-gating-solana.md) Token Gating Getting Started Guide
{% endhint %}

{% tabs %}
{% tab title="EVM-Compatible Chains" %}

```typescript
await picket.auth({
    // any supported EVM-compatible chain
    // if omitted, defaults to "ethereum"
    chain: "ethereum",
    walletAddress: "0x_WALLET_ADDRESS", 
    signature: "SIGNATURE",
    requirements: {
        // restrict access to token holders
        contractAddress: "0xCONTRACT_ADDRESS", 
        // omit if any number of tokens are acceptable
        minTokenBalance: 1
    }
});
```

{% endtab %}

{% tab title="Solana" %}

```typescript
await picket.auth({
    chain: "solana",
    walletAddress: "0x_WALLET_ADDRESS",
    signature: "SIGNATURE",
    requirements: {
        // Replace this the tokens you want to verify ownership for
        // the token ID is the mint associated with a SPL token
        // user needs to own the minTokenBalance of at least one of the listed token 
        tokenIds: ["78AZe2223PknLYT9mn2VCJPAsdvuB6LzFAhgQeVoxddW", "2dQG4YYunFrbJjzW6UTcUmePs8UDy5jz43H6uSCZSAcS"],
        // Replace with minimum balance you want to verify users' currently hold across all token IDs, 
        // or omit if any number of tokens is sufficient
        minTokenBalance: 1 
    },
});
```

{% endtab %}
{% endtabs %}

### Authz

{% hint style="info" %}
**Incremental Authorization (Authz)**

To understand the use-cases for using `authz` over `auth`, read about [Incremental Authorization](/picket-docs/reference/concepts/incremental-authorization.md)
{% endhint %}

`authz` stands for authorization. Unlike [Auth](#auth), which handles both authentication and authorization, [Authz](#undefined) only handles authorization. Given an authenticated user's access token and authorization requirements, `authz` will issue a new access token on success (user is authorized) or, on failure, it will return a 4xx HTTP error code.

{% tabs %}
{% tab title="EVM-Compatible Chains" %}

```typescript
await picket.authz({
    // chain and wallet is stored within the access token
    accessToken: "xxx.yyy.zzz",
    requirements: {
        // check ownership of a specific contract address
        contractAddress: "0xCONTRACT_ADDRESS", 
        // omit if any number of tokens are acceptable
        minTokenBalance: 1
    }
});
```

{% endtab %}

{% tab title="Solana" %}

```typescript
await picket.authz({
    // chain and wallet is stored within the access token
    accessToken: "xxx.yyy.zzz",
    requirements: {
        // check ownership of a specific Metaplex Collection
        collection: "96d973e49267f6bf5b9d68c577fc04ce93757e2c5ae8c086ef6115b3aeee300c", 
        // omit if any number of tokens are acceptable
        minTokenBalance: 1
    }
});
```

{% endtab %}
{% endtabs %}

### Verify Token Ownership

If you only want to verify token ownership server side for a given wallet, `tokenOwnership` allows you to do just that.&#x20;

{% tabs %}
{% tab title="EVM-Compatible Chains" %}

```typescript
import Picket from "@picketapi/picket-node"
const picket = new Picket('YOUR_SECRET_KEY_HERE')

const requirements = {
    // any supported EVM-compatible chain
    // if omitted, defaults to "ethereum"
    chain: "ethereum",
    walletAddress: "WALLET_ADDRESS",
    // Replace this example address with whichever contract you are verifying ownership for
    contractAddress: '0x8a90cab2b38dba80c64b7734e58ee1db38b8992e', 
    // Replace with minimum balance you want to verify users' currently hold.
    minTokenBalance: 1 
}

const { allowed, contractAddress, numTokens } = await picket.tokenOwnership(requirements)
console.log(`Allowed == ${allowed} because ${request.walletAddress} has ${numTokens} for ${contractAddress}.`)
```

{% endtab %}

{% tab title="Solana" %}

```typescript
import Picket from "@picketapi/picket-node"
const picket = new Picket('YOUR_SECRET_KEY_HERE')

const requirements = {
    chain: "solana",
    walletAddress: "WALLET_ADDRESS",
     // Replace this the tokens you want to verify ownership for
    // the token ID is the mint associated with a SPL token
    // user needs to own the minTokenBalance of at least one of the listed token 
    tokenIds: ["78AZe2223PknLYT9mn2VCJPAsdvuB6LzFAhgQeVoxddW", "2dQG4YYunFrbJjzW6UTcUmePs8UDy5jz43H6uSCZSAcS"],
    // Replace with minimum balance you want to verify users' currently hold across all token IDs, 
    // or omit if any number of tokens is sufficient
    minTokenBalance: 1 
}

const { allowed, contractAddress, numTokens } = await picket.tokenOwnership(requirements)
console.log(`Allowed == ${allowed} because ${requirements.walletAddress} has ${numTokens} for ${contractAddress}.`)Validate
```

{% endtab %}
{% endtabs %}

### Validate

`validate` [validates an access token](/picket-docs/reference/concepts/access-tokens.md#validate-an-access-token). `validate` should be called, or manually access token validation should be done, server-side before trusting a request's access token. It's common to move access token validation and decoding logic to a shared middleware across API endpoints.

If the access token is valid, `validate` returns the decoded claims of the access token.

```typescript
const decoded = await picket.validate("ACCESS_TOKEN");
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.picketapi.com/picket-docs/reference/libraries-and-sdks/node.js-library-picket-node.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
