# DeepBook Margin SDK

*[Documentation index](/llms.txt) · [Full index](/llms-full.txt)*

The DeepBook Margin TypeScript SDK abstracts away the transaction calls, allowing for direct interactions with the `DeepBook Margin` package for leveraged trading.

- [SDK repository](https://github.com/MystenLabs/ts-sdks/tree/main/packages/deepbook-v3)
- [NPM version](https://www.npmjs.com/package/@mysten/deepbook-v3)

## Install

To use the SDK in your projects, install the `@mysten/deepbook-v3` package, which includes the margin trading functionality.

```sh npm2yarn
npm install @mysten/deepbook-v3
```

## Constants

The DeepBook SDK includes a constants file (`/utils/constants.ts`) that maintains the latest deployed addresses for DeepBook Margin, as well as margin pools and configurations.

**`constants.ts`**

```ts reference
https://github.com/MystenLabs/ts-sdks/blob/main/packages/deepbook-v3/src/utils/constants.ts
```

## DeepBookClient

To work with DeepBook Margin, use the client extension to add DeepBook functionality to a Sui client. The [Sui TypeScript SDK](https://sdk.mystenlabs.com/typescript) provides the `SuiGrpcClient` and key functionality necessary to process transactions. The following example imports those libraries, as well.

:::info

The code examples in this section use Sui Foundation-managed RPC endpoints for illustration purposes. For production use, replace the `baseUrl` value with your own RPC provider endpoint.

:::

```tsx

class DeepBookMarginTrader {
	client: ClientWithExtensions<{ deepbook: DeepBookClient }>;
	keypair: Ed25519Keypair;

	constructor(privateKey: string, env: 'testnet' | 'mainnet') {
		this.keypair = this.getSignerFromPK(privateKey);
		this.client = new SuiGrpcClient({
			network: env,
			baseUrl:
				env === 'mainnet'
					? 'https://fullnode.mainnet.sui.io:443'
					: 'https://fullnode.testnet.sui.io:443',
		}).$extend(
			deepbook({
				address: this.getActiveAddress(),
			}),
		);
	}

	getSignerFromPK = (privateKey: string): Ed25519Keypair => {
		const { scheme, secretKey } = decodeSuiPrivateKey(privateKey);
		if (scheme === 'ED25519') return Ed25519Keypair.fromSecretKey(secretKey);

		throw new Error(`Unsupported scheme: ${scheme}`);
	};

	getActiveAddress() {
		return this.keypair.toSuiAddress();
	}
}
```

## Keys: Coin, Pool, and MarginManager {#keys}

Functions that require the input of a coin, pool, or a margin manager require the key of any such object as the parameter. The SDK manages a `key:value` relationship of this data in memory. Some default data comes with the SDK (as seen in `utils/constants.ts`). Coins are stored in a `CoinMap`, pools in a `PoolMap`, and margin managers in a `MarginManagerMap` in the config.

### Margin manager

Before placing any margin trade, you must supply a margin manager address to the client. The manager key points to an object defined by the `MarginManager` interface in the client. [MarginManager docs](/onchain-finance/deepbook-margin/contract-information/margin-manager). Initialize the margin manager with the client. If you don't create a margin manager, you can rely on the client to create one, but then the user must reinitialize the client.

Example using an existing margin manager:

```tsx

config();

const MARGIN_MANAGER_KEY = 'MARGIN_MANAGER_1';

class DeepBookMarginTrader {
	client: ClientWithExtensions<{ deepbook: DeepBookClient }>;
	keypair: Ed25519Keypair;

	constructor(privateKey: string, env: 'testnet' | 'mainnet') {
		this.keypair = this.getSignerFromPK(privateKey);
		this.client = new SuiGrpcClient({
			network: env,
			baseUrl:
				env === 'mainnet'
					? 'https://fullnode.mainnet.sui.io:443'
					: 'https://fullnode.testnet.sui.io:443',
		}).$extend(
			deepbook({
				address: this.getActiveAddress(),
				marginManagers: this.getMarginManagers(),
			}),
		);
	}

	getSignerFromPK = (privateKey: string): Ed25519Keypair => {
		const { scheme, secretKey } = decodeSuiPrivateKey(privateKey);
		if (scheme === 'ED25519') return Ed25519Keypair.fromSecretKey(secretKey);

		throw new Error(`Unsupported scheme: ${scheme}`);
	};

	getActiveAddress() {
		return this.keypair.toSuiAddress();
	}

	getMarginManagers(): { [key: string]: MarginManager } {
		const marginManagerAddress = process.env.MARGIN_MANAGER_ADDRESS;
		const poolKey = process.env.POOL_KEY || 'SUI_DBUSDC';
		if (!marginManagerAddress) {
			throw new Error('No margin manager address found');
		}
		return {
			[MARGIN_MANAGER_KEY]: {
				address: marginManagerAddress,
				poolKey: poolKey,
			},
		};
	}
}
```

Example creating a margin manager:

```tsx

const MARGIN_MANAGER_KEY = 'MARGIN_MANAGER_1';

class DeepBookMarginTrader {
	client: ClientWithExtensions<{ deepbook: DeepBookClient }>;
	keypair: Ed25519Keypair;
	env: 'testnet' | 'mainnet';

	constructor(privateKey: string, env: 'testnet' | 'mainnet') {
		this.env = env;
		this.keypair = this.getSignerFromPK(privateKey);
		this.client = this.#createClient(env);
	}

	#createClient(env: 'testnet' | 'mainnet', marginManagers?: { [key: string]: MarginManager }) {
		return new SuiGrpcClient({
			network: env,
			baseUrl:
				env === 'mainnet'
					? 'https://fullnode.mainnet.sui.io:443'
					: 'https://fullnode.testnet.sui.io:443',
		}).$extend(
			deepbook({
				address: this.getActiveAddress(),
				marginManagers,
			}),
		);
	}

	getSignerFromPK = (privateKey: string): Ed25519Keypair => {
		const { scheme, secretKey } = decodeSuiPrivateKey(privateKey);
		if (scheme === 'ED25519') return Ed25519Keypair.fromSecretKey(secretKey);

		throw new Error(`Unsupported scheme: ${scheme}`);
	};

	getActiveAddress() {
		return this.keypair.toSuiAddress();
	}

	async createMarginManagerAndReinitialize() {
		let tx = new Transaction();
		const poolKey = 'SUI_DBUSDC';
		tx.add(this.client.deepbook.marginManager.newMarginManager(poolKey));

		const result = await this.client.core.signAndExecuteTransaction({
			transaction: tx,
			signer: this.keypair,
			include: { effects: true, objectTypes: true },
		});

		if (result.$kind === 'FailedTransaction') {
			throw new Error('Transaction failed');
		}

		const objectTypes = result.Transaction?.objectTypes ?? {};
		const marginManagerAddress = result.Transaction?.effects?.changedObjects?.find(
			(obj) =>
				obj.idOperation === 'Created' && objectTypes[obj.objectId]?.includes('MarginManager'),
		)?.objectId;

		if (!marginManagerAddress) {
			throw new Error('Failed to create margin manager');
		}

		const marginManagers: { [key: string]: MarginManager } = {
			[MARGIN_MANAGER_KEY]: {
				address: marginManagerAddress,
				poolKey: poolKey,
			},
		};

		this.client = this.#createClient(this.env, marginManagers);
	}
}
```

### Coin

The SDK comes with four default coins on Testnet and five default coins on Mainnet.

**Default Testnet coins**

- DEEP
- SUI
- DBUSDC
- DBUSDT

**Default Mainnet coins**

- DEEP
- SUI
- USDC
- USDT
- WETH

You can also initialize the SDK with custom coins to interact with margin pools that are not supported by default. To do this, create a `CoinMap` object and pass it to the constructor of the client.

### Pool

Similar to coins, the SDK comes with default pools. You can provide a `PoolMap` during construction to override this behavior.

```tsx

```

### Example setup

The following example uses the default pools and coins provided, and demonstrates margin trading operations.

```tsx

(async () => {
	const privateKey = ''; // Can encapsulate this in a .env file

	// Initialize with margin managers if created
	const marginManagers = {
		MARGIN_MANAGER_1: {
			address: '',
			poolKey: 'SUI_DBUSDC',
		},
	};
	const traderClient = new DeepBookMarginTrader(privateKey, 'testnet', marginManagers);

	const tx = new Transaction();

	// Margin manager contract calls
	traderClient.client.deepbook.marginManager.deposit('MARGIN_MANAGER_1', 'DBUSDC', 10000)(tx);
	traderClient.client.deepbook.marginManager.borrowBase('MARGIN_MANAGER_1', 'SUI_DBUSDC', 100)(tx);

	// Place leveraged orders
	traderClient.client.deepbook.poolProxy.placeLimitOrder({
		poolKey: 'SUI_DBUSDC',
		marginManagerKey: 'MARGIN_MANAGER_1',
		clientOrderId: '12345',
		price: 2.5,
		quantity: 100,
		isBid: true,
		payWithDeep: true,
	})(tx);

	// Margin pool operations
	const supplierCap = tx.add(traderClient.client.deepbook.marginPool.mintSupplierCap());
	traderClient.client.deepbook.marginPool.supplyToMarginPool('DBUSDC', supplierCap, 5000)(tx);

	let res = await traderClient.signAndExecute(tx);

	console.dir(res, { depth: null });
})();
```

## Margin manager referral functions

The SDK provides functions for managing referrals with margin managers. Referrals are pool-specific and must first be minted using the core DeepBook SDK before they can be associated with a margin manager.

```tsx
// Set a referral for a margin manager (pool-specific)
// The referral must be a DeepBookPoolReferral minted for the pool the margin manager is associated with
traderClient.client.deepbook.marginManager.setMarginManagerReferral(
	'MARGIN_MANAGER_1',
	referralId,
)(tx);

// Unset the referral for a margin manager for a specific pool
traderClient.client.deepbook.marginManager.unsetMarginManagerReferral(
	'MARGIN_MANAGER_1',
	'SUI_DBUSDC',
)(tx);
```

:::info

To mint a referral, use the core DeepBook SDK's `mintReferral` function. See the [DeepBookV3 SDK documentation](/onchain-finance/deepbookv3-sdk#referral-functions) for more details on minting and managing referrals.

:::
