npm package: @muralpay/browser-sdk
Description: End-User Custodial Browser SDK for Mural
Author: Mural Pay Inc.
Latest version: 2.0.1

# End-User Custodial Browser SDK Documentation

## Overview

The End-User Custodial Browser SDK is a TypeScript/JavaScript library that enables secure wallet functionality for browser-based applications. It provides secure key management and transaction signing capabilities.

This guide walks you through the full **end-user custodial payout** flow:

1. Initializing the SDK
2. Triggering a user challenge
3. Initializing the SDK with a verification code
4. Signing the payout
5. Executing the payout

---

## Installation

```bash
npm install @muralpay/browser-sdk
```

---

## 1. Create the SDK Instance

Before using the SDK, mount the authentication iframe in your app.

### Configuration

| Field               | Type          | Description                                                 |
| ------------------- | ------------- | ----------------------------------------------------------- |
| `iframeContainerId` | `string`      | The ID of the HTML element where the iframe will be mounted |
| `iframeElement`     | `HTMLElement` | The actual HTML element (must match the ID above)           |

**HTML:**

```html
<div id="auth-iframe-container-id"></div>
```

**JavaScript:**

```ts
import { EndUserCustodialSDK } from '@muralpay/browser-sdk';

const sdk = await EndUserCustodialSDK.createInstance({
  iframeContainerId: 'auth-iframe-container-id',
  iframeElement: document.getElementById('auth-iframe-container-id'),
});
```

---

## 2. Trigger Challenge

Trigger an authentication challenge for the user by calling your backend API:

```http
POST /approvers/end-user-custodial/initiate-challenge
```

**Payload:**

- `publicKey` — Use `sdk.getPublicKey()`
- `approverId` — The end-user custodial user's ID

```ts
const publicKey = sdk.getPublicKey();
```

**Response:** Contains `authorizationId` for use in next step.

---

## 3. Initialize Session with Verification Code

Once the user receives their **email verification code**, collect it and call:

```ts
await sdk.startSession({
  code: 'code-from-user-email',
  authenticatorId: 'authorization-id-from-initiate-challenge',
});
```

This creates a secure, authenticated session.

---

## 4. Sign the Payout

First, retrieve the payload to sign:

```http
GET /payout/end-user-custodial/body-to-sign/:id
```

- `:id` is the payout request ID

Then sign it:

```ts
const signature = await sdk.signPayoutPayload(body); // use the exact body as returned
```

⚠️ **Important:** Do not alter the body returned by the API. Modifications will invalidate the signature.

---

## 5. Execute the Payout

Send the signature to your backend to execute the payout:

```http
POST /payout/end-user-custodial/execute/:id
```

**Body:**

```json
{
  "signature": "<signature-from-sdk>"
}
```

---

## SDK API Reference

### Static Methods

#### `createInstance(config: EndUserCustodialSDKConfig): Promise<EndUserCustodialSDK>`

Creates and initializes the SDK instance.

```ts
const sdk = await EndUserCustodialSDK.createInstance(config);
```

---

### Instance Methods

#### `startSession(payload: { code: string, authenticatorId: string }): Promise<void>`

Initializes the SDK session using the verification code and `authorizationId`.

```ts
await sdk.startSession({
  code: 'email-code',
  authenticatorId: 'auth-id',
});
```

#### `getPublicKey(): string`

Returns the iframe public key to use in the challenge.

```ts
const publicKey = sdk.getPublicKey();
```

#### `signPayoutPayload(payload: any): Promise<string>`

Signs a payout transaction.

```ts
const signature = await sdk.signPayoutPayload(body);
```

#### `isSessionActive(): boolean`

Checks if a session is currently active.

```ts
if (sdk.isSessionActive()) {
  // Safe to proceed
}
```

#### `clearSession(): void`

Clears the session state.

```ts
sdk.clearSession();
```

#### `getClientSessionExpiry(): Date | null`

Returns the session's expiration time.

```ts
const expiry = sdk.getClientSessionExpiry();
```

---

## Full Usage Flow

```ts
// 1. Create SDK instance
const sdk = await EndUserCustodialSDK.createInstance({
  iframeContainerId: 'auth-iframe-container-id',
  iframeElement: document.getElementById('auth-iframe-container-id'),
});

// 2. Get public key
const publicKey = sdk.getPublicKey();

// 3. Backend: trigger challenge with publicKey + user ID

// 4. User inputs email code → initialize session
await sdk.startSession({
  code: codeFromUser,
  authenticatorId: authIdFromBackend,
});

// 5. Backend: fetch /body-to-sign/:id
const signature = await sdk.signPayoutPayload(body);

// 6. Backend: send signature to /execute/:id
```

---

## Type Definitions

```ts
interface EndUserCustodialSDKConfig {
  iframeContainerId: string;
  iframeElement: HTMLElement;
}

interface TransactionBodyData {
  to: string;
  value: string;
}
```

## Integration with Mural API

This SDK is designed to work seamlessly with the **Mural API** to enable complete end-user custodial payment solutions for your customers.

### What You Can Build:

- **Customer Management**: Create and manage customer accounts
- **End-User Custodial Payments**: Enable secure, self-custody transactions
- **Payout Systems**: Automated or manual payout workflows
- **Multi-signature Wallets**: Enterprise-grade security features

### Getting Started:

1. **SDK Integration**: Use this browser SDK for frontend wallet functionality
2. **API Integration**: Connect your backend to our Mural API for customer management
3. **Complete Flow**: Customers can securely sign transactions without you holding their keys

For API documentation, integration examples, and technical support, contact us at **support@muralpay.com**

---

## Error Handling

The SDK throws clear errors for:

- Missing config or parameters
- Invalid or expired sessions
- Incorrect or altered payloads
- Network or signing failures

Wrap all SDK interactions in `try/catch`:

```ts
try {
  const sdk = await EndUserCustodialSDK.createInstance(...);
} catch (err) {
  console.error('SDK error:', err);
}
```

---

## Support & Contact

**Questions about integration?** We're here to help!

- 📧 **Email**: support@muralpay.com
- 🔧 **Technical Support**: API documentation, integration examples, and troubleshooting
- 💼 **Business Inquiries**: Custom solutions and enterprise features

---

## License

MIT © Mural Pay Inc.