Skip to content

Commit

Permalink
Merge pull request #179 from nervina-labs/extension
Browse files Browse the repository at this point in the history
Support cota extension
  • Loading branch information
duanyytop authored Oct 14, 2022
2 parents f0b83d0 + 071c729 commit 39c21c2
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 78 deletions.
53 changes: 53 additions & 0 deletions example/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { addressToScript } from '@nervosnetwork/ckb-sdk-utils'
import { Collector } from '../src/collector'
import { Aggregator } from '../src/aggregator'
import { Service } from '../src'
import { generateAddExtensionTx } from '../src/service/cota/extension'

const TEST_PRIVATE_KEY = '0xee56672e70cec79941adc0637c1edb1546a0c39c72eff8c41bc4f1e03bf663b3'
const TEST_ADDRESS = 'ckt1qyq897k5m53wxzup078jwkucvvsu8kzv55rqqm6glm'

const secp256k1CellDep = (isMainnet: boolean): CKBComponents.CellDep => {
if (isMainnet) {
return {
outPoint: {
txHash: '0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c',
index: '0x0',
},
depType: 'depGroup',
}
}
return {
outPoint: {
txHash: '0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37',
index: '0x0',
},
depType: 'depGroup',
}
}

const run = async () => {
// True for mainnet and false for testnet
const isMainnet = false

const service: Service = {
collector: new Collector({
ckbNodeUrl: 'https://testnet.ckb.dev/rpc',
ckbIndexerUrl: 'https://testnet.ckb.dev/indexer',
}),
aggregator: new Aggregator({ registryUrl: 'http://localhost:3050', cotaUrl: 'http://localhost:3030' }),
}
const ckb = service.collector.getCkb()
const extensionLock = addressToScript(TEST_ADDRESS)

let rawTx = await generateAddExtensionTx(service, extensionLock, BigInt(6000), isMainnet)
rawTx.cellDeps.push(secp256k1CellDep(isMainnet))

const signedTx = ckb.signTransaction(TEST_PRIVATE_KEY)(rawTx)
console.log(JSON.stringify(signedTx))

let txHash = await ckb.rpc.sendTransaction(signedTx, 'passthrough')
console.info(`Add cota extension tx has been sent with tx hash ${txHash}`)
}

run()
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nervina-labs/cota-sdk",
"version": "0.6.6",
"version": "0.7.0",
"description": "The SDK of CoTA",
"repository": "[email protected]:nervina-labs/cota-sdk-js.git",
"author": "duanyytop <[email protected]>",
Expand Down
6 changes: 6 additions & 0 deletions src/aggregator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
GetDefineInfoReq,
GetIssuerInfoReq,
GetCotaCountReq,
ExtensionReq,
} from '../types/request'
import {
ClaimResp,
Expand All @@ -37,6 +38,7 @@ import {
GetDefineInfoResp,
GetIssuerInfoResp,
GetCotaCountResp,
ExtensionResp,
} from '../types/response'
import { Byte32 } from '../types/common'

Expand Down Expand Up @@ -159,6 +161,10 @@ export class Aggregator {
async getCotaCount(req: GetCotaCountReq): Promise<GetCotaCountResp> {
return (await this.baseRPC('get_cota_count', req)) as Promise<GetCotaCountResp>
}

async generateExtensionSmt(extension: ExtensionReq): Promise<ExtensionResp> {
return (await this.baseRPC('generate_extension_smt', extension)) as Promise<ExtensionResp>
}
}

const convert = (req: GetCotaReq) => ({
Expand Down
4 changes: 3 additions & 1 deletion src/service/cota/claim-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ export const generateClaimUpdateCotaTx = async (
nfts,
}

const { smtRootHash, claimUpdateSmtEntry, withdrawBlockHash } = await service.aggregator.generateClaimUpdateCotaSmt(claimUpdateReq)
const { smtRootHash, claimUpdateSmtEntry, withdrawBlockHash } = await service.aggregator.generateClaimUpdateCotaSmt(
claimUpdateReq,
)
const outputsData = [`0x02${smtRootHash}`]
const cellDeps = [getCotaCellDep(isMainnet)]
const headerDeps = [`0x${withdrawBlockHash}`]
Expand Down
138 changes: 69 additions & 69 deletions src/service/cota/cota-meta.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,69 @@
import { Service } from '../..'
import { FEE, getCotaTypeScript, getCotaCellDep } from '../../constants'
import { CotaInfo, Hex } from '../../types'
import { append0x, utf8ToHex, toSnakeCase } from '../../utils'

const generateCotaMetadata = (cotaInfo: CotaInfo, cotaId: Hex): Hex => {
const cotaInfoTemp = {
cotaId,
...cotaInfo,
}
const cotaMeta = {
id: 'CTMeta',
ver: '1.0',
metadata: {
target: 'output#0',
type: 'cota',
data: {
version: '0',
...cotaInfoTemp,
},
},
}
return append0x(utf8ToHex(JSON.stringify(toSnakeCase(cotaMeta))))
}

export const generateCotaMetadataTx = async (
service: Service,
cotaLock: CKBComponents.Script,
cotaId: Hex,
cotaInfo: CotaInfo,
fee = FEE,
isMainnet = false,
) => {
const cotaType = getCotaTypeScript(isMainnet)
const cotaCells = await service.collector.getCells(cotaLock, cotaType)
if (!cotaCells || cotaCells.length === 0) {
throw new Error("Cota cell doesn't exist")
}

const cotaCell = cotaCells[0]
const inputs = [
{
previousOutput: cotaCell.outPoint,
since: '0x0',
},
]

const outputs = [cotaCell.output]
outputs[0].capacity = `0x${(BigInt(outputs[0].capacity) - fee).toString(16)}`

const cotaOutput = await service.collector.getLiveCell(cotaCell.outPoint)
const outputsData = [cotaOutput.data?.content]

const cellDeps = [getCotaCellDep(isMainnet)]

const rawTx: any = {
version: '0x0',
cellDeps,
headerDeps: [],
inputs,
outputs,
outputsData,
witnesses: [],
}
rawTx.witnesses = rawTx.inputs.map((_, i) =>
i > 0 ? '0x' : { lock: '', inputType: '', outputType: generateCotaMetadata(cotaInfo, cotaId) },
)
return rawTx
}
import { Service } from '../..'
import { FEE, getCotaTypeScript, getCotaCellDep } from '../../constants'
import { CotaInfo, Hex } from '../../types'
import { append0x, utf8ToHex, toSnakeCase } from '../../utils'

const generateCotaMetadata = (cotaInfo: CotaInfo, cotaId: Hex): Hex => {
const cotaInfoTemp = {
cotaId,
...cotaInfo,
}
const cotaMeta = {
id: 'CTMeta',
ver: '1.0',
metadata: {
target: 'output#0',
type: 'cota',
data: {
version: '0',
...cotaInfoTemp,
},
},
}
return append0x(utf8ToHex(JSON.stringify(toSnakeCase(cotaMeta))))
}

export const generateCotaMetadataTx = async (
service: Service,
cotaLock: CKBComponents.Script,
cotaId: Hex,
cotaInfo: CotaInfo,
fee = FEE,
isMainnet = false,
) => {
const cotaType = getCotaTypeScript(isMainnet)
const cotaCells = await service.collector.getCells(cotaLock, cotaType)
if (!cotaCells || cotaCells.length === 0) {
throw new Error("Cota cell doesn't exist")
}

const cotaCell = cotaCells[0]
const inputs = [
{
previousOutput: cotaCell.outPoint,
since: '0x0',
},
]

const outputs = [cotaCell.output]
outputs[0].capacity = `0x${(BigInt(outputs[0].capacity) - fee).toString(16)}`

const cotaOutput = await service.collector.getLiveCell(cotaCell.outPoint)
const outputsData = [cotaOutput.data?.content]

const cellDeps = [getCotaCellDep(isMainnet)]

const rawTx: any = {
version: '0x0',
cellDeps,
headerDeps: [],
inputs,
outputs,
outputsData,
witnesses: [],
}
rawTx.witnesses = rawTx.inputs.map((_, i) =>
i > 0 ? '0x' : { lock: '', inputType: '', outputType: generateCotaMetadata(cotaInfo, cotaId) },
)
return rawTx
}
76 changes: 76 additions & 0 deletions src/service/cota/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { serializeScript } from '@nervosnetwork/ckb-sdk-utils'
import { Service } from '../..'
import { FEE, getCotaTypeScript, getCotaCellDep } from '../../constants'
import { ExtensionReq } from '../../types'


enum Action {
Add,
Update
}

const generateExtensionTx = async (
service: Service,
cotaLock: CKBComponents.Script,
fee = FEE,
isMainnet = false,
action: Action,
) => {
const cotaType = getCotaTypeScript(isMainnet)
const cotaCells = await service.collector.getCells(cotaLock, cotaType)
if (!cotaCells || cotaCells.length === 0) {
throw new Error("Cota cell doesn't exist")
}
const cotaCell = cotaCells[0]
const inputs = [
{
previousOutput: cotaCell.outPoint,
since: '0x0',
},
]

const outputs = [cotaCell.output]
outputs[0].capacity = `0x${(BigInt(outputs[0].capacity) - fee).toString(16)}`

const extensionReq: ExtensionReq = {
lockScript: serializeScript(cotaLock),
}

const { smtRootHash, extensionSmtEntry } = await service.aggregator.generateExtensionSmt(extensionReq)
const cotaCellData = `0x02${smtRootHash}`

const outputsData = [cotaCellData]
const cellDeps = [getCotaCellDep(isMainnet)]

const rawTx = {
version: '0x0',
cellDeps,
headerDeps: [],
inputs,
outputs,
outputsData,
witnesses: [],
} as any

const prefix = action == Action.Add ? '0xF0' : '0xF1'
rawTx.witnesses = rawTx.inputs.map((_, i) =>
i > 0 ? '0x' : { lock: '', inputType: `${prefix}${extensionSmtEntry}`, outputType: '' },
)
return rawTx
}


export const generateAddExtensionTx = async (
service: Service,
cotaLock: CKBComponents.Script,
fee = FEE,
isMainnet = false
) => await generateExtensionTx(service, cotaLock, fee, isMainnet, Action.Add)


export const generateUpdateExtensionTx = async (
service: Service,
cotaLock: CKBComponents.Script,
fee = FEE,
isMainnet = false
) => await generateExtensionTx(service, cotaLock, fee, isMainnet, Action.Update)
5 changes: 2 additions & 3 deletions src/service/cota/transfer-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ export const generateTransferUpdateCotaTx = async (
transferOutPoint: append0x(serializeOutPoint(cotaCell.outPoint).slice(26)),
transfers,
}
const { smtRootHash, transferUpdateSmtEntry, withdrawBlockHash } = await service.aggregator.generateTransferUpdateCotaSmt(
transferUpdateReq,
)
const { smtRootHash, transferUpdateSmtEntry, withdrawBlockHash } =
await service.aggregator.generateTransferUpdateCotaSmt(transferUpdateReq)
const outputsData = [`0x02${smtRootHash}`]

const cellDeps = [getCotaCellDep(isMainnet)]
Expand Down
6 changes: 4 additions & 2 deletions src/service/cota/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ export const generateTransferCotaTx = async (
transferOutPoint: append0x(serializeOutPoint(cotaCell.outPoint).slice(26)),
transfers,
}
const { smtRootHash, transferSmtEntry, withdrawBlockHash } = await service.aggregator.generateTransferCotaSmt(transferReq)
const { smtRootHash, transferSmtEntry, withdrawBlockHash } = await service.aggregator.generateTransferCotaSmt(
transferReq,
)
const outputsData = [`0x02${smtRootHash}`]

const cellDeps = [getCotaCellDep(isMainnet)]
const headerDeps = [`0x${withdrawBlockHash}`]

const rawTx = {
version: '0x0',
cellDeps,
Expand Down
5 changes: 3 additions & 2 deletions src/service/registry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ export const generateRegisterCotaTx = async (
outputs[length - 1].capacity = `0x${(BigInt(outputs[length - 1].capacity) - fee).toString(16)}`

const lockHashes = cotaLocks.map(lock => scriptToHash(lock))
const { smtRootHash, registrySmtEntry, outputAccountNum } = await service.aggregator.generateRegisterCotaSmt(lockHashes)
const { smtRootHash, registrySmtEntry, outputAccountNum } = await service.aggregator.generateRegisterCotaSmt(
lockHashes,
)
const registryCellData = `0x01${smtRootHash}${u64ToBe(BigInt(outputAccountNum))}`

const outputsData = outputs.map((_, i) => (i === 0 ? registryCellData : i !== outputs.length - 1 ? '0x02' : '0x'))
Expand All @@ -97,7 +99,6 @@ export const generateRegisterCotaTx = async (
return rawTx
}


export const generateUpdateCcidsTx = async (
service: Service,
fee = FEE,
Expand Down
4 changes: 4 additions & 0 deletions src/types/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,7 @@ export interface GetCotaCountReq extends SmtReq {
lockScript: Bytes
cotaId: Byte20
}

export interface ExtensionReq extends SmtReq {
lockScript: Bytes
}
6 changes: 6 additions & 0 deletions src/types/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,9 @@ export interface GetCotaCountResp {
count: number
blockNumber: bigint
}

export interface ExtensionResp extends SmtResp {
smtRootHash: Byte32
extensionSmtEntry: Bytes
blockNumber: bigint
}

0 comments on commit 39c21c2

Please sign in to comment.