# Installation via Package Manager

# Installation via package manager

For any project with a bundler: install the packages, set the config in a module that runs first, and declare global {
  interface Window {
    FrakSetup: { config?: FrakWalletSdkConfig };
  }
}

window.FrakSetup = {
  config: {
    metadata: {
      name: "Your Store",
      currency: "eur",
    },
  },
};
```

**Targeting the dev stage:** `env` states both origins the SDK talks to: `"prod"` (the default), `"dev"`, or an explicit `{ wallet, backend }` pair for local development. It replaces `walletUrl` and lands in the next major of the SDK, so on the version published today use `walletUrl` instead. See [Configuration](/developers/concepts/configuration/).

Every field is listed on the [FrakSetup reference](/developers/components/frak-setup/) and in [Configuration](/developers/concepts/configuration/).

## 3. Register the components

Import your config module first, then each component you use. The imports are side-effectful: they register the custom element and boot the SDK from `window.FrakSetup.config`.

```ts title="main.ts"
function waitForClient(): Promise<FrakClient> {
  if (window.FrakSetup?.client) return Promise.resolve(window.FrakSetup.client);
  return new Promise((resolve) => {
    window.addEventListener(
      "frak:client",
      () => resolve(window.FrakSetup.client as FrakClient),
      { once: true }
    );
  });
}

const client = await waitForClient();

await watchWalletStatus(client, (status) => {
  console.log(status.key === "connected" ? status.wallet : "not connected");
});

await displayModal(client, {
  steps: {
    login: {},
    final: { action: { key: "sharing" } },
  },
});
```

### Track a purchase

```ts
await trackPurchaseStatus({
  customerId: "cust_123",
  orderId: "order_456",
  token: "a-unique-order-token",
});
```

Rewards are only released once your backend confirms the order with a signed webhook. See [Validate purchases from your backend](/guides/platforms/custom/backend/).

### What is available

| Action | Purpose |
| --- | --- |
| `watchWalletStatus` | Current wallet status, plus every change |
| `displayModal` | Open a modal built from steps (`login`, `final`, and more) |
| `displaySharingPage` | Open the sharing page directly |
| `displayEmbeddedWallet` | Open the embedded wallet view |
| `sendInteraction` | Send an interaction, fire and forget |
| `trackPurchaseStatus` | Register an order so a confirmed sale can pay a reward |
| `referralInteraction`, `processReferral`, `setupReferral` | Handle an inbound referral |
| `getMerchantInformation` | Your merchant data as resolved by the backend |
| `getUserReferralStatus`, `getMergeToken` | Referral state and wallet merge token |
| `openSso`, `prepareSso`, `prepareSsoUrl` | Single sign-on flows |
| `siweAuthenticate` | Sign-In with Ethereum |
| `sendTransaction` | Ask the wallet to send a transaction |
| `modalBuilder` | Fluent builder for modal steps |

Full signatures live in the [generated SDK reference](/developers/references/readme/).

### Other entry points

`@frak-labs/core-sdk` also exposes `/rewards` and `/identity` subpaths, and `/bundle` (index plus actions in one import) for CDN-style consumption.

## Advanced: create the client yourself

If you do not use the components package, create the client by hand. Call `setupClient` **once** and reuse the promise: each call recreates the listener iframe.

```ts title="frak-client.ts"
const config: FrakWalletSdkConfig = {
  metadata: { name: "Your Store" },
};

let clientPromise: ReturnType<typeof setupClient> | undefined;

export function getFrakClient() {
  clientPromise ??= setupClient({ config });
  return clientPromise;
}
```

## Next steps

[Components reference](/developers/components/)
  [React integration](/developers/integration/react/)
  [CDN setup](/developers/integration/cdn/)
  [Interactions](/developers/concepts/interactions/)