# Register Signer (/docs/risex/api/register-signer)

# Authentication: Register Signer

Before making any authenticated API calls, you need to register a signer. The signer is a private key that will be used to sign transactions on behalf of your account.

## Step 1: Generate Signer Key

```typescript
// Generate a new private key for the signer
const signingKey = generatePrivateKey();
const signerAccount = privateKeyToAccount(signingKey);
const signerAddress = signerAccount.address; // This is your signer address
```

## Step 2: Create Account Signature (User Wallet Signature)

The account owner signs a `RegisterSigner` EIP-712 message authorizing the signer. The nonce system uses a
bitmap-based approach with `nonceAnchor` (epoch) and `nonceBitmap` (bit index) for replay protection.

```typescript
const createAccountSignature = async (
  signerAddress: `0x${string}`,
  nonceAnchor: bigint, // uint48 nonce epoch anchor
  nonceBitmap: number, // uint8 bit index within nonce bitmap
  authContractAddress: `0x${string}`,
  // You'll need a wallet provider (like wagmi, ethers, etc.)
  signTypedDataAsync: (data: any) => Promise<string>,
) => {
  const expiration = dayjs().add(7, 'day').unix(); // 7 days from now

  const registerMessage = {
    signer: signerAddress,
    message: 'Please sign in with your wallet to access RISEx.',
    expiration,
    nonceAnchor,
    nonceBitmap,
  };

  const domain = getRISExDomain(authContractAddress);

  // User signs with their wallet
  const accountSignature = await signTypedDataAsync({
    types: REGISTER_TYPES,
    message: {
      signer: registerMessage.signer,
      message: registerMessage.message,
      expiration: registerMessage.expiration,
      nonceAnchor: registerMessage.nonceAnchor,
      nonceBitmap: registerMessage.nonceBitmap,
    },
    primaryType: 'RegisterSigner',
    domain: domain as any,
  });

  return {
    accountSignature,
    registerMessage,
  };
};
```

## Step 3: Register Signer via API

```typescript
const registerSigner = async (
  account: `0x${string}`,
  authContractAddress: `0x${string}`,
  nonceAnchor: bigint,
  nonceBitmap: number,
  signTypedDataAsync: (data: any) => Promise<string>,
) => {
  try {
    // Step 1: Generate signer key
    const signingKey = generatePrivateKey();
    const signerAccount = privateKeyToAccount(signingKey);
    const signerAddress = signerAccount.address;

    // Step 2: Get user wallet signature
    const { accountSignature, registerMessage } = await createAccountSignature(
      signerAddress as `0x${string}`,
      nonceAnchor,
      nonceBitmap,
      authContractAddress,
      signTypedDataAsync,
    );

    // Step 3: Register via API
    const response = await apiClient.post('/v1/auth/register-signer', {
      account: account,
      signer: registerMessage.signer,
      message: registerMessage.message,
      nonce_anchor: nonceAnchor.toString(),
      nonce_bitmap: nonceBitmap,
      expiration: registerMessage.expiration.toString(),
      account_signature: accountSignature,
    });

    if (response.data) {
      console.log('Signer registered successfully:', {
        account,
        signer: signerAddress,
        signingKey, // Store this securely!
        expiration: registerMessage.expiration,
      });

      // IMPORTANT: Store signingKey securely for future API calls
      return {
        signer: signerAddress,
        signingKey, // Keep this secret!
      };
    }
  } catch (error) {
    if (axios.isAxiosError(error)) {
      console.error('Failed to register signer:', error.response?.data?.message || error.message);
    } else {
      console.error('Failed to register signer:', error);
    }
    throw error;
  }
};
```

## Important Notes

* **One-time setup**: Register signer once per account
* **Store securely**: Keep the `signingKey` private and secure - it authorizes all transactions
* **Expiration**: Signers expire after the expiration time (typically 7 days)
* **Re-registration**: You may need to re-register if the signer expires
* **No signer signature required**: Only the account owner's signature is needed to register a signer
* **Permissions**: Signers are granted `Permission.All` by default. Use `enablePermission`/`disablePermission` on the authorization contract to manage granular permissions (Perps, Spot, MoveFund)
