본문으로 건너뛰기

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