Skip to content

Commit

Permalink
support SUDT asset
Browse files Browse the repository at this point in the history
  • Loading branch information
duanyytop committed Feb 19, 2024
1 parent cbed079 commit 82a5c24
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 82 deletions.
65 changes: 41 additions & 24 deletions src/order/cancel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
MAX_FEE,
JOYID_ESTIMATED_WITNESS_LOCK_SIZE,
CKB_UNIT,
getSudtDep,
} from '../constants'
import { CancelParams, SubkeyUnlockReq, TakerResult } from '../types'
import { CKBAsset, CancelParams, Hex, SubkeyUnlockReq, TakerResult } from '../types'
import { append0x } from '../utils'
import { UdtException, NoCotaCellException, NoLiveCellException } from '../exceptions'
import {
Expand All @@ -20,7 +21,14 @@ import {
import { CKBTransaction } from '@joyid/ckb'
import { OrderArgs } from './orderArgs'

export const buildCancelTx = async ({ collector, joyID, seller, orderOutPoints, fee }: CancelParams): Promise<TakerResult> => {
export const buildCancelTx = async ({
collector,
joyID,
seller,
orderOutPoints,
fee,
ckbAsset = CKBAsset.XUDT,
}: CancelParams): Promise<TakerResult> => {
let txFee = fee ?? MAX_FEE
const isMainnet = seller.startsWith('ckb')
const sellerLock = addressToScript(seller)
Expand Down Expand Up @@ -53,36 +61,45 @@ export const buildCancelTx = async ({ collector, joyID, seller, orderOutPoints,
orderCells.push(cell)
}

const { udtOutputs, udtOutputsData, sumUdtCapacity } = cleanUpUdtOutputs(orderCells, sellerLock)
let inputs: CKBComponents.CellInput[] = []
const outputs: CKBComponents.CellOutput[] = []
const outputsData: Hex[] = []
let cellDeps: CKBComponents.CellDep[] = [getDexCellDep(isMainnet)]
let changeCapacity = BigInt(0)

const outputs = udtOutputs
const outputsData = udtOutputsData

const minCellCapacity = calculateEmptyCellMinCapacity(sellerLock)
const needCKB = ((minCellCapacity + minCellCapacity + CKB_UNIT) / CKB_UNIT).toString()
const errMsg = `At least ${needCKB} free CKB (refundable) is required to cancel the sell order.`
const { inputs: emptyInputs, capacity: inputsCapacity } = collector.collectInputs(
emptyCells,
minCellCapacity,
txFee,
minCellCapacity,
errMsg,
)
const orderInputs: CKBComponents.CellInput[] = outPoints.map(outPoint => ({
previousOutput: outPoint,
since: '0x0',
}))
const inputs = [...orderInputs, ...emptyInputs]
if (ckbAsset === CKBAsset.XUDT || ckbAsset === CKBAsset.SUDT) {
const { udtOutputs, udtOutputsData, sumUdtCapacity } = cleanUpUdtOutputs(orderCells, sellerLock)

const changeCapacity = inputsCapacity + orderInputsCapacity - sumUdtCapacity - txFee
const changeOutput: CKBComponents.CellOutput = {
lock: sellerLock,
capacity: append0x(changeCapacity.toString(16)),
const outputs = udtOutputs
const outputsData = udtOutputsData

const minCellCapacity = calculateEmptyCellMinCapacity(sellerLock)
const needCKB = ((minCellCapacity + minCellCapacity + CKB_UNIT) / CKB_UNIT).toString()
const errMsg = `At least ${needCKB} free CKB (refundable) is required to cancel the sell order.`
const { inputs: emptyInputs, capacity: inputsCapacity } = collector.collectInputs(
emptyCells,
minCellCapacity,
txFee,
minCellCapacity,
errMsg,
)
inputs = [...orderInputs, ...emptyInputs]

const changeCapacity = inputsCapacity + orderInputsCapacity - sumUdtCapacity - txFee
const changeOutput: CKBComponents.CellOutput = {
lock: sellerLock,
capacity: append0x(changeCapacity.toString(16)),
}
outputs.push(changeOutput)
outputsData.push('0x')

cellDeps.push(ckbAsset === CKBAsset.XUDT ? getXudtDep(isMainnet) : getSudtDep(isMainnet))
}
outputs.push(changeOutput)
outputsData.push('0x')

let cellDeps: CKBComponents.CellDep[] = [getXudtDep(isMainnet), getDexCellDep(isMainnet)]
if (joyID) {
cellDeps.push(getJoyIDCellDep(isMainnet))
}
Expand Down
68 changes: 37 additions & 31 deletions src/order/maker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
MAX_FEE,
JOYID_ESTIMATED_WITNESS_LOCK_SIZE,
CKB_UNIT,
getSudtDep,
} from '../constants'
import { Hex, SubkeyUnlockReq, MakerParams, MakerResult, CKBAsset } from '../types'
import { append0x, u128ToLe } from '../utils'
Expand All @@ -24,7 +25,7 @@ export const buildMakerTx = async ({
totalValue,
assetType,
fee,
asset = CKBAsset.XUDT,
ckbAsset = CKBAsset.XUDT,
}: MakerParams): Promise<MakerResult> => {
let txFee = fee ?? MAX_FEE
const isMainnet = seller.startsWith('ckb')
Expand Down Expand Up @@ -55,45 +56,50 @@ export const buildMakerTx = async ({
errMsg,
)

const udtCells = await collector.getCells({
lock: sellerLock,
type: assetTypeScript,
})
if (!udtCells || udtCells.length === 0) {
throw new UdtException('The address has no UDT cells')
}
let { inputs, capacity: udtInputsCapacity, amount: inputsAmount } = collector.collectUdtInputs(udtCells, listAmount)
inputs = [...emptyInputs, ...inputs]

// build dex and other outputs and outputsData
let inputs: CKBComponents.CellInput[] = []
const outputs: CKBComponents.CellOutput[] = []
const outputsData: Hex[] = []
let cellDeps: CKBComponents.CellDep[] = []
let changeCapacity = BigInt(0)

outputs.push({
lock: orderLock,
type: assetTypeScript,
capacity: append0x(orderCellCapacity.toString(16)),
})
outputsData.push(append0x(u128ToLe(listAmount)))
if (ckbAsset === CKBAsset.XUDT || ckbAsset === CKBAsset.SUDT) {
const udtCells = await collector.getCells({
lock: sellerLock,
type: assetTypeScript,
})
if (!udtCells || udtCells.length === 0) {
throw new UdtException('The address has no UDT cells')
}
const { inputs: udtInputs, capacity: udtInputsCapacity, amount: inputsAmount } = collector.collectUdtInputs(udtCells, listAmount)
inputs = [...emptyInputs, ...udtInputs]

let changeCapacity = emptyInputsCapacity + udtInputsCapacity - orderCellCapacity - txFee
if (inputsAmount > listAmount) {
const udtCellCapacity = calculateUdtCellCapacity(sellerLock, assetTypeScript)
changeCapacity -= udtCellCapacity
outputs.push({
lock: sellerLock,
lock: orderLock,
type: assetTypeScript,
capacity: append0x(udtCellCapacity.toString(16)),
capacity: append0x(orderCellCapacity.toString(16)),
})
outputsData.push(append0x(u128ToLe(inputsAmount - listAmount)))
outputsData.push(append0x(u128ToLe(listAmount)))

changeCapacity = emptyInputsCapacity + udtInputsCapacity - orderCellCapacity - txFee
if (inputsAmount > listAmount) {
const udtCellCapacity = calculateUdtCellCapacity(sellerLock, assetTypeScript)
changeCapacity -= udtCellCapacity
outputs.push({
lock: sellerLock,
type: assetTypeScript,
capacity: append0x(udtCellCapacity.toString(16)),
})
outputsData.push(append0x(u128ToLe(inputsAmount - listAmount)))
}
outputs.push({
lock: sellerLock,
capacity: append0x(changeCapacity.toString(16)),
})
outputsData.push('0x')

cellDeps.push(ckbAsset === CKBAsset.XUDT ? getXudtDep(isMainnet) : getSudtDep(isMainnet))
}
outputs.push({
lock: sellerLock,
capacity: append0x(changeCapacity.toString(16)),
})
outputsData.push('0x')

let cellDeps: CKBComponents.CellDep[] = [getXudtDep(isMainnet)]
if (joyID) {
cellDeps.push(getJoyIDCellDep(isMainnet))
}
Expand Down
69 changes: 43 additions & 26 deletions src/order/taker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
MAX_FEE,
JOYID_ESTIMATED_WITNESS_LOCK_SIZE,
CKB_UNIT,
getSudtDep,
} from '../constants'
import { Hex, SubkeyUnlockReq, TakerParams, TakerResult } from '../types'
import { CKBAsset, Hex, SubkeyUnlockReq, TakerParams, TakerResult } from '../types'
import { append0x } from '../utils'
import { UdtException, NoCotaCellException, NoLiveCellException } from '../exceptions'
import { calculateEmptyCellMinCapacity, calculateTransactionFee, deserializeOutPoints, cleanUpUdtOutputs } from './helper'
Expand All @@ -34,7 +35,14 @@ export const matchOrderOutputs = (orderCells: CKBComponents.LiveCell[]) => {
return { orderOutputs, orderOutputsData, sumOrderCapacity }
}

export const buildTakerTx = async ({ collector, joyID, buyer, orderOutPoints, fee }: TakerParams): Promise<TakerResult> => {
export const buildTakerTx = async ({
collector,
joyID,
buyer,
orderOutPoints,
fee,
ckbAsset = CKBAsset.XUDT,
}: TakerParams): Promise<TakerResult> => {
let txFee = fee ?? MAX_FEE
const isMainnet = buyer.startsWith('ckb')
const buyerLock = addressToScript(buyer)
Expand Down Expand Up @@ -62,38 +70,47 @@ export const buildTakerTx = async ({ collector, joyID, buyer, orderOutPoints, fe
orderCells.push(cell)
}

let inputs: CKBComponents.CellInput[] = []
const outputs: CKBComponents.CellOutput[] = []
const outputsData: Hex[] = []
let cellDeps: CKBComponents.CellDep[] = [getDexCellDep(isMainnet)]
let changeCapacity = BigInt(0)

const { orderOutputs, orderOutputsData, sumOrderCapacity } = matchOrderOutputs(orderCells)
const { udtOutputs, udtOutputsData, sumUdtCapacity } = cleanUpUdtOutputs(orderCells, buyerLock)

const needInputsCapacity = sumOrderCapacity + sumUdtCapacity
const outputs = [...orderOutputs, ...udtOutputs]
const outputsData = [...orderOutputsData, ...udtOutputsData]

const minCellCapacity = calculateEmptyCellMinCapacity(buyerLock)
const needCKB = ((needInputsCapacity + minCellCapacity + CKB_UNIT) / CKB_UNIT).toString()
const errMsg = `At least ${needCKB} free CKB is required to take the order.`
const { inputs: emptyInputs, capacity: inputsCapacity } = collector.collectInputs(
emptyCells,
needInputsCapacity,
txFee,
minCellCapacity,
errMsg,
)
const orderInputs: CKBComponents.CellInput[] = outPoints.map(outPoint => ({
previousOutput: outPoint,
since: '0x0',
}))
const inputs = [...orderInputs, ...emptyInputs]
if (ckbAsset === CKBAsset.XUDT || ckbAsset === CKBAsset.SUDT) {
const { udtOutputs, udtOutputsData, sumUdtCapacity } = cleanUpUdtOutputs(orderCells, buyerLock)

const changeCapacity = inputsCapacity - needInputsCapacity - txFee
const changeOutput: CKBComponents.CellOutput = {
lock: buyerLock,
capacity: append0x(changeCapacity.toString(16)),
const needInputsCapacity = sumOrderCapacity + sumUdtCapacity
const outputs = [...orderOutputs, ...udtOutputs]
const outputsData = [...orderOutputsData, ...udtOutputsData]

const minCellCapacity = calculateEmptyCellMinCapacity(buyerLock)
const needCKB = ((needInputsCapacity + minCellCapacity + CKB_UNIT) / CKB_UNIT).toString()
const errMsg = `At least ${needCKB} free CKB is required to take the order.`
const { inputs: emptyInputs, capacity: inputsCapacity } = collector.collectInputs(
emptyCells,
needInputsCapacity,
txFee,
minCellCapacity,
errMsg,
)
inputs = [...orderInputs, ...emptyInputs]

changeCapacity = inputsCapacity - needInputsCapacity - txFee
const changeOutput: CKBComponents.CellOutput = {
lock: buyerLock,
capacity: append0x(changeCapacity.toString(16)),
}
outputs.push(changeOutput)
outputsData.push('0x')

cellDeps.push(ckbAsset === CKBAsset.XUDT ? getXudtDep(isMainnet) : getSudtDep(isMainnet))
}
outputs.push(changeOutput)
outputsData.push('0x')

let cellDeps: CKBComponents.CellDep[] = [getXudtDep(isMainnet), getDexCellDep(isMainnet)]
if (joyID) {
cellDeps.push(getJoyIDCellDep(isMainnet))
}
Expand Down
2 changes: 1 addition & 1 deletion src/types/dex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface BaseParams {
collector: Collector
fee?: bigint
joyID?: JoyIDConfig
asset?: CKBAsset
ckbAsset?: CKBAsset
}

export interface MakerParams extends BaseParams {
Expand Down

0 comments on commit 82a5c24

Please sign in to comment.