# 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](https://docs.picketapi.com/picket-docs/tutorials/link-a-wallet-to-a-web-2.0-account).&#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](https://docs.picketapi.com/picket-docs/quick-start-guides/quick-start-guides/token-gating-ethereum-evm) or [Solana](https://docs.picketapi.com/picket-docs/quick-start-guides/quick-start-guides/token-gating-solana) 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](https://docs.picketapi.com/picket-docs/reference/concepts/incremental-authorization)
{% 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](https://docs.picketapi.com/picket-docs/concepts/access-tokens#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");
```
