본문으로 건너뛰기

DeepBookV3 SDK

DeepBookV3 TypeScript SDK는 트랜잭션 calls를 추상화하여 DeepBook 패키지와 직접 상호작용할 수 있도록 한다.

설치​

프로젝트에서 SDK를 사용하려면 @mysten/deepbook 패키지를 설치한다.

npm install @mysten/deepbook-v3

constant​

DeepBookV3 SDK에는 DeepBookV3의 최신 deployed 주소와 몇 가지 staple 코인 및 풀을 유지하는 constants file(/utils/constants.ts)이 포함되어 있다.

DeepBookClient​

DeepBookV3로 작업하려면 클라이언트 extension을 사용하여 Sui 클라이언트에 DeepBook 기능을 추가한다. Sui TypeScript SDK는 트랜잭션을 처리하는 데 필요한 SuiGrpcClient와 주요 기능을 제공한다. 다음 예시는 해당 라이브러리도 함께 import한다.

import { deepbook, type DeepBookClient } from '@mysten/deepbook-v3';
import type { ClientWithExtensions } from '@mysten/sui/client';
import { SuiGrpcClient } from '@mysten/sui/grpc';
import { decodeSuiPrivateKey } from '@mysten/sui/cryptography';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';

class DeepBookMarketMaker {
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 Manager​

코인, 풀, 또는 manager를 입력으로 요구하는 함수는 파라미터로 해당 객체의 key를 요구한다. SDK는 이 데이터의 key:value 관계를 memory에서 관리한다. 일부 기본값 data는 SDK에 포함되어 있다(utils/constants.ts에서 볼 수 있다). 코인은 CoinMap에 저장되고 풀은 config의 PoolMap에 저장된다.

BalanceManager​

어떤 trade를 배치하기 전에 클라이언트에 BalanceManager 주소를 제공해야 한다. manager key는 클라이언트의 BalanceManager 인터페이스로 정의된 객체를 가리킨다. BalanceManager docs. 클라이언트로 BalanceManager를 초기화한다. BalanceManager를 생성하지 않으면 클라이언트가 대신 생성하도록 할 수 있지만, 그러면 사용자는 클라이언트를 다시 초기화해야 한다.

기존 BalanceManager를 사용하는 예시:

import { deepbook, type DeepBookClient } from '@mysten/deepbook-v3';
import type { ClientWithExtensions } from '@mysten/sui/client';
import type { BalanceManager } from '@mysten/deepbook-v3';
import { SuiGrpcClient } from '@mysten/sui/grpc';
import { decodeSuiPrivateKey } from '@mysten/sui/cryptography';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import { config } from 'dotenv';

config();

const BALANCE_MANAGER_KEY = 'MANAGER_1';

class DeepBookMarketMaker {
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(),
balanceManagers: this.getBalanceManagers(),
}),
);
}

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();
}

getBalanceManagers(): { [key: string]: BalanceManager } {
const balanceManagerAddress = process.env.BALANCE_MANAGER_ADDRESS;
const balanceManagerTradeCap = process.env.BALANCE_MANAGER_TRADE_CAP;
if (!balanceManagerAddress) {
throw new Error('No balance manager address found');
}
return {
[BALANCE_MANAGER_KEY]: {
address: balanceManagerAddress,
tradeCap: balanceManagerTradeCap,
},
};
}
}

BalanceManager를 생성하는 예시:

import { deepbook, type DeepBookClient } from '@mysten/deepbook-v3';
import type { ClientWithExtensions } from '@mysten/sui/client';
import type { BalanceManager } from '@mysten/deepbook-v3';
import { SuiGrpcClient } from '@mysten/sui/grpc';
import { decodeSuiPrivateKey } from '@mysten/sui/cryptography';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import { Transaction } from '@mysten/sui/transactions';

const BALANCE_MANAGER_KEY = 'MANAGER_1';

class DeepBookMarketMaker {
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', balanceManagers?: { [key: string]: BalanceManager }) {
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(),
balanceManagers,
}),
);
}

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 createBalanceManagerAndReinitialize() {
let tx = new Transaction();
tx.add(this.client.deepbook.balanceManager.createAndShareBalanceManager());

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 balanceManagerAddress = result.Transaction?.effects?.changedObjects?.find(
(obj) => obj.idOperation === 'Created' && objectTypes[obj.objectId]?.includes('BalanceManager'),
)?.objectId;

if (!balanceManagerAddress) {
throw new Error('Failed to create balance manager');
}

const balanceManagers: { [key: string]: BalanceManager } = {
[BALANCE_MANAGER_KEY]: {
address: balanceManagerAddress,
tradeCap: undefined,
},
};

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

Coin​

SDK는 Testnet에서 네 개의 기본 코인과 Mainnet에서 다섯 개의 기본 코인을 제공한다.

Default Testnet 코인

  • DEEP
  • SUI
  • DBUSDC
  • DBUSDT

Default Mainnet 코인

  • DEEP
  • SUI
  • USDC
  • USDT
  • WETH

기본적으로 지원되지 않는 풀과 상호작용하기 위해 custom 코인으로 SDK를 초기화할 수도 있다. 이를 위해 CoinMap 객체를 생성하여 클라이언트의 constructor에 전달한다.

풀​

코인과 마찬가지로 SDK에는 기본 풀이 포함되어 있다. 이 동작을 override하려면 생성 시 PoolMap을 제공할 수 있다.

import { deepbook, type DeepBookClient } from '@mysten/deepbook-v3';
import type { ClientWithExtensions } from '@mysten/sui/client';
import type { BalanceManager } from '@mysten/deepbook-v3';
import { SuiGrpcClient } from '@mysten/sui/grpc';
import { decodeSuiPrivateKey } from '@mysten/sui/cryptography';
import type { Keypair } from '@mysten/sui/cryptography';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import type { Transaction } from '@mysten/sui/transactions';

export class DeepBookMarketMaker {
keypair: Keypair;
client: ClientWithExtensions<{ deepbook: DeepBookClient }>;

constructor(
keypair: string | Keypair,
env: 'testnet' | 'mainnet',
balanceManagers?: { [key: string]: BalanceManager },
adminCap?: string,
) {
if (typeof keypair === 'string') {
this.keypair = DeepBookMarketMaker.#getSignerFromPK(keypair);
} else {
this.keypair = keypair;
}

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(),
balanceManagers,
adminCap,
}),
);
}

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

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

signAndExecute = async (tx: Transaction) => {
const result = await this.client.core.signAndExecuteTransaction({
transaction: tx,
signer: this.keypair,
include: { effects: true },
});
if (result.$kind === 'FailedTransaction') {
throw new Error('Transaction failed');
}
return result.Transaction;
};

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

예시 setup​

다음 예시는 제공된 기본 풀과 코인을 사용한다.

import { Transaction } from '@mysten/sui/transactions';

import { DeepBookMarketMaker } from './deepbookMarketMaker.js';

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

// Initialize with balance managers if created
const balanceManagers = {
MANAGER_1: {
address: '',
tradeCap: '',
},
};
const mmClient = new DeepBookMarketMaker(privateKey, 'testnet', balanceManagers);

const tx = new Transaction();

// Read only call
console.log(await mmClient.client.deepbook.checkManagerBalance('MANAGER_1', 'SUI'));
console.log(await mmClient.client.deepbook.getLevel2Range('SUI_DBUSDC', 0.1, 100, true));

// Balance manager contract call
mmClient.client.deepbook.balanceManager.depositIntoManager('MANAGER_1', 'DBUSDT', 10000)(tx);
mmClient.client.deepbook.balanceManager.withdrawAllFromManager(
'MANAGER_1',
'DBUSDT',
mmClient.getActiveAddress(),
)(tx);

let res = await mmClient.signAndExecute(tx);

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

리퍼럴 함수​

SDK는 풀-specific referrals를 관리하기 위한 함수를 제공한다. Referrals는 사용자가 자신이 refer한 traders로부터 거래 수수료의 일부를 벌 수 있도록 한다.

Pool referral 함수​

이 함수는 풀 level에서 referrals를 관리하기 위해 deepbook contract에서 사용할 수 있다.

Multiplier constraints

referral multiplier는 0.1의 배수(예: 0.1, 0.2, 0.3, ...)여야 하며 2.0을 초과할 수 없다.

// Mint a new referral for a specific pool
// multiplier determines the portion of fees allocated to the referrer
// Valid values: 0.1, 0.2, 0.3, ... up to 2.0
client.deepbook.mintReferral('SUI_DBUSDC', 0.1)(tx);

// Update the multiplier for an existing referral
client.deepbook.updatePoolReferralMultiplier('SUI_DBUSDC', referralId, 0.2)(tx);

// Claim accumulated referral rewards (returns base, quote, and DEEP coins)
const { baseRewards, quoteRewards, deepRewards } = tx.add(
client.deepbook.claimPoolReferralRewards('SUI_DBUSDC', referralId)
);

// Get the current balances for a referral
client.deepbook.getPoolReferralBalances('SUI_DBUSDC', referralId)(tx);

// Get the multiplier for a referral
client.deepbook.poolReferralMultiplier('SUI_DBUSDC', referralId)(tx);

BalanceManager referral 함수​

이 함수는 referrals를 BalanceManager와 연결하기 위해 balanceManager contract에서 사용할 수 있다.

// Generate a trade cap first (needed for setting referrals)
const tradeCap = tx.add(client.deepbook.balanceManager.mintTradeCap('MANAGER_1'));

// Set a referral for a balance manager (pool-specific)
// Each balance manager can have different referrals for different pools
client.deepbook.balanceManager.setBalanceManagerReferral('MANAGER_1', referralId, tradeCap)(tx);

// Unset the referral for a specific pool
client.deepbook.balanceManager.unsetBalanceManagerReferral('MANAGER_1', 'SUI_DBUSDC', tradeCap)(tx);

// Get the referral ID associated with a balance manager for a specific pool
client.deepbook.balanceManager.getBalanceManagerReferralId('MANAGER_1', 'SUI_DBUSDC')(tx);

// Get the owner of a referral
client.deepbook.balanceManager.balanceManagerReferralOwner(referralId)(tx);

// Get the pool ID associated with a referral
client.deepbook.balanceManager.balanceManagerReferralPoolId(referralId)(tx);