Skip to content

Commit

Permalink
refactor udt asset
Browse files Browse the repository at this point in the history
  • Loading branch information
duanyytop committed Feb 19, 2024
1 parent 5c7300f commit cbed079
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 84 deletions.
2 changes: 1 addition & 1 deletion example/cancel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const cancel = async () => {
const signedTx = signSecp256r1Tx(key, rawTx, witnessIndex)

let txHash = await collector.getCkb().rpc.sendTransaction(signedTx, 'passthrough')
console.info(`The xudt asset has been cancelled with tx hash: ${txHash}`)
console.info(`The udt asset has been cancelled with tx hash: ${txHash}`)
}

cancel()
4 changes: 2 additions & 2 deletions example/maker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ const maker = async () => {
seller,
listAmount,
totalValue,
xudtType: append0x(serializeScript(xudtType)),
assetType: append0x(serializeScript(xudtType)),
})

const key = keyFromP256Private(SELLER_MAIN_PRIVATE_KEY)
const signedTx = signSecp256r1Tx(key, rawTx)

let txHash = await collector.getCkb().rpc.sendTransaction(signedTx, 'passthrough')
console.info(`The xudt asset has been listed with tx hash: ${txHash}`)
console.info(`The udt asset has been listed with tx hash: ${txHash}`)
}

maker()
2 changes: 1 addition & 1 deletion example/taker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const taker = async () => {
console.log(JSON.stringify(signedTx))

let txHash = await collector.getCkb().rpc.sendTransaction(signedTx, 'passthrough')
console.info(`The taker of xudt asset has been finished with tx hash: ${txHash}`)
console.info(`The taker of udt asset has been finished with tx hash: ${txHash}`)
}

taker()
10 changes: 5 additions & 5 deletions src/collector/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import axios from 'axios'
import CKB from '@nervosnetwork/ckb-sdk-core'
import { toCamelcase } from '../utils/case-parser'
import { IndexerCell, CollectResult, IndexerCapacity, CollectXudtResult } from '../types/collector'
import { CKB_UNIT, MIN_CAPACITY } from '../constants'
import { CapacityNotEnoughException, IndexerException, XudtAmountNotEnoughException } from '../exceptions'
import { IndexerCell, CollectResult, IndexerCapacity, CollectUdtResult as CollectUdtResult } from '../types/collector'
import { MIN_CAPACITY } from '../constants'
import { CapacityNotEnoughException, IndexerException, UdtAmountNotEnoughException } from '../exceptions'
import { leToU128 } from '../utils'

export class Collector {
Expand Down Expand Up @@ -141,7 +141,7 @@ export class Collector {
return { inputs, capacity: sum }
}

collectXudtInputs(liveCells: IndexerCell[], needAmount: bigint): CollectXudtResult {
collectUdtInputs(liveCells: IndexerCell[], needAmount: bigint): CollectUdtResult {
let inputs: CKBComponents.CellInput[] = []
let sumCapacity = BigInt(0)
let sumAmount = BigInt(0)
Expand All @@ -160,7 +160,7 @@ export class Collector {
}
}
if (sumAmount < needAmount) {
throw new XudtAmountNotEnoughException('Insufficient Xudt balance')
throw new UdtAmountNotEnoughException('Insufficient UDT balance')
}
return { inputs, capacity: sumCapacity, amount: sumAmount }
}
Expand Down
31 changes: 31 additions & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ const TestnetInfo = {
},
depType: 'code',
} as CKBComponents.CellDep,

SUDTTypeScript: {
codeHash: '0xc5e5dcf215925f7ef4dfaf5f4b4f105bc321c02776d6e7d52a1db3fcd9d011a4',
hashType: 'type',
args: '',
} as CKBComponents.Script,

SUDTTypeDep: {
outPoint: {
txHash: '0xe12877ebd2c3c364dc46c5c992bcfaf4fee33fa13eebdf82c591fc9825aab769',
index: '0x0',
},
depType: 'code',
} as CKBComponents.CellDep,
}

const MainnetInfo = {
Expand Down Expand Up @@ -120,6 +134,20 @@ const MainnetInfo = {
},
depType: 'code',
} as CKBComponents.CellDep,

SUDTTypeScript: {
codeHash: '0x5e7a36a77e68eecc013dfa2fe6a23f3b6c344b04005808694ae6dd45eea4cfd5',
hashType: 'type',
args: '',
} as CKBComponents.Script,

SUDTTypeDep: {
outPoint: {
txHash: '0xc7813f6a415144643970c2e88e0bb6ca6a8edc5dd7c1022746f628284a9936d5',
index: '0x0',
},
depType: 'code',
} as CKBComponents.CellDep,
}

export const getJoyIDLockScript = (isMainnet = false) => (isMainnet ? MainnetInfo.JoyIDLockScript : TestnetInfo.JoyIDLockScript)
Expand All @@ -133,3 +161,6 @@ export const getDexCellDep = (isMainnet = false) => (isMainnet ? MainnetInfo.Dex

export const getXudtTypeScript = (isMainnet = false) => (isMainnet ? MainnetInfo.XUDTTypeScript : TestnetInfo.XUDTTypeScript)
export const getXudtDep = (isMainnet = false) => (isMainnet ? MainnetInfo.XUDTTypeDep : TestnetInfo.XUDTTypeDep)

export const getSudtTypeScript = (isMainnet = false) => (isMainnet ? MainnetInfo.SUDTTypeScript : TestnetInfo.SUDTTypeScript)
export const getSudtDep = (isMainnet = false) => (isMainnet ? MainnetInfo.SUDTTypeDep : TestnetInfo.SUDTTypeDep)
4 changes: 2 additions & 2 deletions src/exceptions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export class CapacityNotEnoughException extends Error {
}
}

export class XudtAmountNotEnoughException extends Error {
export class UdtAmountNotEnoughException extends Error {
constructor(message: string) {
super(message)
}
Expand All @@ -16,7 +16,7 @@ export class IndexerException extends Error {
}
}

export class XudtException extends Error {
export class UdtException extends Error {
constructor(message: string) {
super(message)
}
Expand Down
25 changes: 15 additions & 10 deletions src/order/cancel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ import {
} from '../constants'
import { CancelParams, SubkeyUnlockReq, TakerResult } from '../types'
import { append0x } from '../utils'
import { XudtException, NoCotaCellException, NoLiveCellException } from '../exceptions'
import { calculateEmptyCellMinCapacity, calculateTransactionFee, cleanUpXudtOutputs, deserializeOutPoints } from './helper'
import { UdtException, NoCotaCellException, NoLiveCellException } from '../exceptions'
import {
calculateEmptyCellMinCapacity,
calculateTransactionFee,
cleanUpUdtOutputs as cleanUpUdtOutputs,
deserializeOutPoints,
} from './helper'
import { CKBTransaction } from '@joyid/ckb'
import { OrderArgs } from './orderArgs'

Expand All @@ -30,28 +35,28 @@ export const buildCancelTx = async ({ collector, joyID, seller, orderOutPoints,
const outPoints = deserializeOutPoints(orderOutPoints)

let orderInputsCapacity = BigInt(0)
// Fetch xudt order cells with outPoints
// Fetch udt order cells with outPoints
const orderCells: CKBComponents.LiveCell[] = []
for await (const outPoint of outPoints) {
const cell = await collector.getLiveCell(outPoint)
if (!cell) {
throw new XudtException('The xudt cell specified by the out point has been spent')
throw new UdtException('The udt cell specified by the out point has been spent')
}
const orderArgs = OrderArgs.fromHex(cell.output.lock.args)
if (serializeScript(orderArgs.ownerLock) !== serializeScript(sellerLock)) {
throw new XudtException('The xudt cell does not belong to the seller address')
throw new UdtException('The udt cell does not belong to the seller address')
}
if (!cell.output.type || !cell.data) {
throw new XudtException('The xudt cell specified by the out point must have type script')
throw new UdtException('The udt cell specified by the out point must have type script')
}
orderInputsCapacity += BigInt(cell.output.capacity)
orderCells.push(cell)
}

const { xudtOutputs, xudtOutputsData, sumXudtCapacity } = cleanUpXudtOutputs(orderCells, sellerLock)
const { udtOutputs, udtOutputsData, sumUdtCapacity } = cleanUpUdtOutputs(orderCells, sellerLock)

const outputs = xudtOutputs
const outputsData = xudtOutputsData
const outputs = udtOutputs
const outputsData = udtOutputsData

const minCellCapacity = calculateEmptyCellMinCapacity(sellerLock)
const needCKB = ((minCellCapacity + minCellCapacity + CKB_UNIT) / CKB_UNIT).toString()
Expand All @@ -69,7 +74,7 @@ export const buildCancelTx = async ({ collector, joyID, seller, orderOutPoints,
}))
const inputs = [...orderInputs, ...emptyInputs]

const changeCapacity = inputsCapacity + orderInputsCapacity - sumXudtCapacity - txFee
const changeCapacity = inputsCapacity + orderInputsCapacity - sumUdtCapacity - txFee
const changeOutput: CKBComponents.CellOutput = {
lock: sellerLock,
capacity: append0x(changeCapacity.toString(16)),
Expand Down
38 changes: 19 additions & 19 deletions src/order/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { blockchain } from '@ckb-lumos/base'
import { serializeScript } from '@nervosnetwork/ckb-sdk-utils'

// minimum occupied capacity and 1 ckb for transaction fee
export const calculateXudtCellCapacity = (lock: CKBComponents.Script, xudtType: CKBComponents.Script): bigint => {
export const calculateUdtCellCapacity = (lock: CKBComponents.Script, udtType: CKBComponents.Script): bigint => {
const lockArgsSize = remove0x(lock.args).length / 2
const typeArgsSize = remove0x(xudtType.args).length / 2
const typeArgsSize = remove0x(udtType.args).length / 2
const cellSize = 33 + lockArgsSize + 33 + typeArgsSize + 8 + 16
return BigInt(cellSize + 1) * CKB_UNIT
}
Expand Down Expand Up @@ -38,30 +38,30 @@ export const deserializeOutPoints = (outPointHexList: Hex[]) => {
return outPoints
}

export const cleanUpXudtOutputs = (orderCells: CKBComponents.LiveCell[], lock: CKBComponents.Script) => {
const orderXudtTypeHexSet = new Set(orderCells.map(cell => serializeScript(cell.output.type!)))
const orderXudtTypes: CKBComponents.Script[] = []
for (const orderXudtTypeHex of orderXudtTypeHexSet) {
orderXudtTypes.push(blockchain.Script.unpack(orderXudtTypeHex) as CKBComponents.Script)
export const cleanUpUdtOutputs = (orderCells: CKBComponents.LiveCell[], lock: CKBComponents.Script) => {
const orderUdtTypeHexSet = new Set(orderCells.map(cell => serializeScript(cell.output.type!)))
const orderUdtTypes: CKBComponents.Script[] = []
for (const orderUdtTypeHex of orderUdtTypeHexSet) {
orderUdtTypes.push(blockchain.Script.unpack(orderUdtTypeHex) as CKBComponents.Script)
}

const xudtOutputs: CKBComponents.CellOutput[] = []
const xudtOutputsData: Hex[] = []
let sumXudtCapacity = BigInt(0)
const udtOutputs: CKBComponents.CellOutput[] = []
const udtOutputsData: Hex[] = []
let sumUdtCapacity = BigInt(0)

for (const orderXudtType of orderXudtTypes) {
sumXudtCapacity += calculateXudtCellCapacity(lock, orderXudtType!)
xudtOutputs.push({
for (const orderUdtType of orderUdtTypes) {
sumUdtCapacity += calculateUdtCellCapacity(lock, orderUdtType!)
udtOutputs.push({
lock: lock,
type: orderXudtType,
capacity: append0x(calculateXudtCellCapacity(lock, orderXudtType!).toString(16)),
type: orderUdtType,
capacity: append0x(calculateUdtCellCapacity(lock, orderUdtType!).toString(16)),
})
const xudtAmount = orderCells
.filter(cell => serializeScript(cell.output.type!) === serializeScript(orderXudtType))
const udtAmount = orderCells
.filter(cell => serializeScript(cell.output.type!) === serializeScript(orderUdtType))
.map(cell => leToU128(cell.data?.content!))
.reduce((prev, current) => prev + current, BigInt(0))
xudtOutputsData.push(append0x(u128ToLe(xudtAmount)))
udtOutputsData.push(append0x(u128ToLe(udtAmount)))
}

return { xudtOutputs, xudtOutputsData, sumXudtCapacity }
return { udtOutputs, udtOutputsData, sumUdtCapacity }
}
2 changes: 1 addition & 1 deletion src/order/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { buildMakerTx } from './maker'
export { buildTakerTx } from './taker'
export { buildCancelTx } from './cancel'
export { calculateXudtCellCapacity, calculateEmptyCellMinCapacity } from './helper'
export { calculateUdtCellCapacity, calculateEmptyCellMinCapacity } from './helper'
export * from './orderArgs'
37 changes: 19 additions & 18 deletions src/order/maker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,27 @@ import {
JOYID_ESTIMATED_WITNESS_LOCK_SIZE,
CKB_UNIT,
} from '../constants'
import { Hex, SubkeyUnlockReq, MakerParams, MakerResult } from '../types'
import { Hex, SubkeyUnlockReq, MakerParams, MakerResult, CKBAsset } from '../types'
import { append0x, u128ToLe } from '../utils'
import { XudtException, NoCotaCellException, NoLiveCellException } from '../exceptions'
import { calculateEmptyCellMinCapacity, calculateTransactionFee, calculateXudtCellCapacity } from './helper'
import { UdtException, NoCotaCellException, NoLiveCellException } from '../exceptions'
import { calculateEmptyCellMinCapacity, calculateTransactionFee, calculateUdtCellCapacity } from './helper'
import { CKBTransaction } from '@joyid/ckb'
import { OrderArgs } from './orderArgs'

export const buildMakerTx = async ({
collector,
joyID,
seller,
listAmount,
listAmount = BigInt(0),
totalValue,
xudtType,
assetType,
fee,
asset = CKBAsset.XUDT,
}: MakerParams): Promise<MakerResult> => {
let txFee = fee ?? MAX_FEE
const isMainnet = seller.startsWith('ckb')
const sellerLock = addressToScript(seller)
const xudtTypeScript = blockchain.Script.unpack(xudtType) as CKBComponents.Script
const assetTypeScript = blockchain.Script.unpack(assetType) as CKBComponents.Script

const emptyCells = await collector.getCells({
lock: sellerLock,
Expand All @@ -41,7 +42,7 @@ export const buildMakerTx = async ({
...getDexLockScript(isMainnet),
args: orderArgs.toHex(),
}
const orderCellCapacity = calculateXudtCellCapacity(orderLock, xudtTypeScript)
const orderCellCapacity = calculateUdtCellCapacity(orderLock, assetTypeScript)

const minCellCapacity = calculateEmptyCellMinCapacity(sellerLock)
const needCKB = ((orderCellCapacity + minCellCapacity + CKB_UNIT) / CKB_UNIT).toString()
Expand All @@ -54,14 +55,14 @@ export const buildMakerTx = async ({
errMsg,
)

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

// build dex and other outputs and outputsData
Expand All @@ -70,19 +71,19 @@ export const buildMakerTx = async ({

outputs.push({
lock: orderLock,
type: xudtTypeScript,
type: assetTypeScript,
capacity: append0x(orderCellCapacity.toString(16)),
})
outputsData.push(append0x(u128ToLe(listAmount)))

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

0 comments on commit cbed079

Please sign in to comment.