Skip to content

Commit

Permalink
Merge pull request #29 from nervina-labs/develop
Browse files Browse the repository at this point in the history
Release v0.1.3
  • Loading branch information
duanyytop authored Mar 1, 2022
2 parents 667bff5 + a5df2dc commit 755886b
Show file tree
Hide file tree
Showing 12 changed files with 303 additions and 39 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ https://testnet.ckbapp.dev/indexer ---> ckb testnet indexer_rpc
- [withdraw example](https://github.com/nervina-labs/cota-sdk-js/blob/develop/example/withdraw.ts): Generate withdrawing CoTA NFT transaction
- [transfer example](https://github.com/nervina-labs/cota-sdk-js/blob/develop/example/transfer.ts): Generate transferring CoTA NFT transaction
- [update example](https://github.com/nervina-labs/cota-sdk-js/blob/develop/example/update.ts): Generate updating CoTA NFT information transaction
- [claim&update example](https://github.com/nervina-labs/cota-sdk-js/blob/develop/example/claim-update.ts): Generate claiming and updateing CoTA NFT transaction
- [transfer&update example](https://github.com/nervina-labs/cota-sdk-js/blob/develop/example/transfer-update.ts): Generate transferring and updating CoTA NFT transaction
45 changes: 45 additions & 0 deletions example/claim-update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { addressToScript } from '@nervosnetwork/ckb-sdk-utils'
import { Collector } from '../src/collector'
import { Aggregator } from '../src/aggregator'
import { generateClaimUpdateCotaTx } from '../src/service/cota'
import { CotaNft, Service } from '../src'
import CKB from '@nervosnetwork/ckb-sdk-core'

const TEST_ADDRESS = 'ckt1qyq0scej4vn0uka238m63azcel7cmcme7f2sxj5ska'
const RECEIVER_PRIVATE_KEY = '0xcf56c11ce3fbec627e5118acd215838d1f9c5048039792d42143f933cde76311'
const RECEIVER_ADDRESS = 'ckt1qyqdcu8n8h5xlhecrd8ut0cf9wer6qnhfqqsnz3lw9'

const secp256k1CellDep = async (ckb: CKB): Promise<CKBComponents.CellDep> => {
const secp256k1Dep = (await ckb.loadDeps()).secp256k1Dep
return { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' }
}

const run = async () => {
const service: Service = {
collector: new Collector({ ckbNodeUrl: 'http://localhost:8114', ckbIndexerUrl: 'http://localhost:8116' }),
aggregator: new Aggregator({ registryUrl: 'http://localhost:3050', cotaUrl: 'http://localhost:3030' }),
}
const ckb = service.collector.getCkb()
const claimLock = addressToScript(RECEIVER_ADDRESS)
const withdrawLock = addressToScript(TEST_ADDRESS)

const nfts: CotaNft[] = [
{
cotaId: '0x678319cdf1f343aa4adf379bafebbb2fc9360ac9',
tokenIndex: '0x00000000',
state: '0x00',
characteristic: '0xa5a5a50505050505050505050505050505050505',
},
]
let rawTx = await generateClaimUpdateCotaTx(service, claimLock, withdrawLock, nfts)

const secp256k1Dep = await secp256k1CellDep(ckb)
rawTx.cellDeps.push(secp256k1Dep)

const signedTx = ckb.signTransaction(RECEIVER_PRIVATE_KEY)(rawTx)
console.log(JSON.stringify(signedTx))
let txHash = await ckb.rpc.sendTransaction(signedTx, 'passthrough')
console.info(`Claim and update cota nft tx has been sent with tx hash ${txHash}`)
}

run()
6 changes: 3 additions & 3 deletions example/mint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ const run = async () => {
const mintLock = addressToScript(TEST_ADDRESS)

const mintCotaInfo: MintCotaInfo = {
cotaId: '0x1deb31f603652bf59ff5027b522e1d81c288b72f',
cotaId: '0x678319cdf1f343aa4adf379bafebbb2fc9360ac9',
withdrawals: [
{
tokenIndex: '0x00000000',
state: '0x00',
characteristic: '0xa505050505050505050505050505050505050505',
characteristic: '0x0505050505050505050505050505050505050505',
toLockScript: serializeScript(addressToScript(RECEIVER_ADDRESS)),
},
{
tokenIndex: '0x00000001',
state: '0x00',
characteristic: '0xa505050505050505050505050505050505050505',
characteristic: '0x0505050505050505050505050505050505050505',
toLockScript: serializeScript(addressToScript(RECEIVER_ADDRESS)),
},
],
Expand Down
47 changes: 47 additions & 0 deletions example/transfer-update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { addressToScript, serializeScript } from '@nervosnetwork/ckb-sdk-utils'
import { Collector } from '../src/collector'
import { Aggregator } from '../src/aggregator'
import { generateTransferUpdateCotaTx } from '../src/service/cota'
import { Service, TransferUpdate } from '../src'
import CKB from '@nervosnetwork/ckb-sdk-core'

const TEST_ADDRESS = 'ckt1qyq0scej4vn0uka238m63azcel7cmcme7f2sxj5ska'
const RECEIVER_PRIVATE_KEY = '0xcf56c11ce3fbec627e5118acd215838d1f9c5048039792d42143f933cde76311'
const RECEIVER_ADDRESS = 'ckt1qyqdcu8n8h5xlhecrd8ut0cf9wer6qnhfqqsnz3lw9'
const OTHER_ADDRESS = 'ckt1qyqz8vxeyrv4nur4j27ktp34fmwnua9wuyqqggd748'

const secp256k1CellDep = async (ckb: CKB): Promise<CKBComponents.CellDep> => {
const secp256k1Dep = (await ckb.loadDeps()).secp256k1Dep
return { outPoint: secp256k1Dep.outPoint, depType: 'depGroup' }
}

const run = async () => {
const service: Service = {
collector: new Collector({ ckbNodeUrl: 'http://localhost:8114', ckbIndexerUrl: 'http://localhost:8116' }),
aggregator: new Aggregator({ registryUrl: 'http://localhost:3050', cotaUrl: 'http://localhost:3030' }),
}
const ckb = service.collector.getCkb()
const cotaLock = addressToScript(RECEIVER_ADDRESS)
const withdrawLock = addressToScript(TEST_ADDRESS)

const transfers: TransferUpdate[] = [
{
cotaId: '0x678319cdf1f343aa4adf379bafebbb2fc9360ac9',
tokenIndex: '0x00000001',
toLockScript: serializeScript(addressToScript(OTHER_ADDRESS)),
state: '0x00',
characteristic: '0x2525250505050505050505050505050505050505',
},
]
let rawTx = await generateTransferUpdateCotaTx(service, cotaLock, withdrawLock, transfers)

const secp256k1Dep = await secp256k1CellDep(ckb)
rawTx.cellDeps.push(secp256k1Dep)

const signedTx = ckb.signTransaction(RECEIVER_PRIVATE_KEY)(rawTx)
console.log(JSON.stringify(signedTx))
let txHash = await ckb.rpc.sendTransaction(signedTx, 'passthrough')
console.info(`Transfer and update cota nft tx has been sent with tx hash ${txHash}`)
}

run()
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nervina-labs/cota-sdk",
"version": "0.1.2",
"version": "0.1.3",
"description": "The SDK of CoTA",
"repository": "[email protected]:nervina-labs/cota-sdk-js.git",
"author": "duanyytop <[email protected]>",
Expand Down Expand Up @@ -33,7 +33,7 @@
"devDependencies": {
"@types/crypto-js": "4.1.1",
"@types/node": "17.0.21",
"@typescript-eslint/parser": "5.12.1",
"@typescript-eslint/parser": "5.13.0",
"babel-eslint": "10.1.0",
"convert-keys": "1.3.4",
"eslint": "8.10.0",
Expand All @@ -44,7 +44,7 @@
"prettier": "2.5.1",
"ts-node": "10.5.0",
"tslib": "2.3.1",
"typescript": "4.5.5"
"typescript": "4.6.2"
},
"homepage": "https://github.com/nervina-labs/cota-sdk-js#readme"
}
12 changes: 12 additions & 0 deletions src/aggregator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
UpdateReq,
WithdrawalReq,
GetCotaSenderReq,
ClaimUpdateReq,
TransferUpdateReq,
} from '../types/request'
import {
ClaimResp,
Expand All @@ -26,6 +28,8 @@ import {
UpdateResp,
WithdrawalResp,
GetCotaSenderResp,
ClaimUpdateResp,
TransferUpdateResp,
} from '../types/response'
import { Byte32 } from '../types/common'

Expand Down Expand Up @@ -93,6 +97,14 @@ export class Aggregator {
return (await this.baseRPC('generate_claim_cota_smt', claim)) as Promise<ClaimResp>
}

async generateTransferUpdateCotaSmt(transfer: TransferUpdateReq): Promise<TransferUpdateResp> {
return (await this.baseRPC('generate_transfer_update_cota_smt', transfer)) as Promise<TransferUpdateResp>
}

async generateClaimUpdateCotaSmt(claim: ClaimUpdateReq): Promise<ClaimUpdateResp> {
return (await this.baseRPC('generate_claim_update_cota_smt', claim)) as Promise<ClaimUpdateResp>
}

async generateUpdateCotaSmt(update: UpdateReq): Promise<UpdateResp> {
return (await this.baseRPC('generate_update_cota_smt', update)) as Promise<UpdateResp>
}
Expand Down
62 changes: 62 additions & 0 deletions src/service/cota/claim-update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { scriptToHash, serializeScript } from '@nervosnetwork/ckb-sdk-utils'
import { Service, CotaNft, ClaimUpdateReq } from '../..'
import { FEE, getCotaTypeScript, getCotaCellDep } from '../../constants'

export const generateClaimUpdateCotaTx = async (
service: Service,
cotaLock: CKBComponents.Script,
withdrawalLock: CKBComponents.Script,
nfts: CotaNft[],
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 withdrawalLockHash = scriptToHash(withdrawalLock)
const withdrawalCotaCells = await service.collector.getCells(withdrawalLock, cotaType)
if (!withdrawalCotaCells || withdrawalCotaCells.length === 0) {
throw new Error("Withdrawal cota cell doesn't exist")
}
const withdrawalCotaCell = withdrawalCotaCells[0]

const claimUpdateReq: ClaimUpdateReq = {
lockScript: serializeScript(cotaLock),
withdrawalLockHash,
nfts,
}

const { smtRootHash, claimUpdateSmtEntry } = await service.aggregator.generateClaimUpdateCotaSmt(claimUpdateReq)
const outputsData = [`0x00${smtRootHash}`]

const withdrawalCellDep: CKBComponents.CellDep = { outPoint: withdrawalCotaCell.outPoint, depType: 'code' }
const cellDeps = [withdrawalCellDep, getCotaCellDep(isMainnet)]

const rawTx = {
version: '0x0',
cellDeps,
headerDeps: [],
inputs,
outputs,
outputsData,
witnesses: [],
}
rawTx.witnesses = rawTx.inputs.map((_, i) =>
i > 0 ? '0x' : { lock: '', inputType: `0x07${claimUpdateSmtEntry}`, outputType: '' },
)
return rawTx
}
2 changes: 2 additions & 0 deletions src/service/cota/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export * from './withdraw'
export * from './claim'
export * from './update'
export * from './transfer'
export * from './claim-update'
export * from './transfer-update'
61 changes: 61 additions & 0 deletions src/service/cota/transfer-update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { scriptToHash, serializeOutPoint, serializeScript } from '@nervosnetwork/ckb-sdk-utils'
import { Service, TransferUpdate, TransferUpdateReq } from '../..'
import { FEE, getCotaTypeScript, getCotaCellDep } from '../../constants'
import { append0x } from '../../utils/hex'

export const generateTransferUpdateCotaTx = async (
service: Service,
cotaLock: CKBComponents.Script,
withdrawalLock: CKBComponents.Script,
transfers: TransferUpdate[],
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 cotaLockScript = serializeScript(cotaLock)
const withdrawalLockHash = scriptToHash(withdrawalLock)
const withdrawalCotaCells = await service.collector.getCells(withdrawalLock, cotaType)
if (!withdrawalCotaCells || withdrawalCotaCells.length === 0) {
throw new Error("Withdrawal cota cell doesn't exist")
}
const withdrawalCotaCell = withdrawalCotaCells[0]

const transferUpdateReq: TransferUpdateReq = {
lockScript: cotaLockScript,
withdrawalLockHash,
transferOutPoint: append0x(serializeOutPoint(cotaCell.outPoint).slice(26)),
transfers,
}
const { smtRootHash, transferUpdateSmtEntry } = await service.aggregator.generateTransferUpdateCotaSmt(transferUpdateReq)
const outputsData = [`0x00${smtRootHash}`]

const withdrawalCellDep: CKBComponents.CellDep = { outPoint: withdrawalCotaCell.outPoint, depType: 'code' }
const cellDeps = [withdrawalCellDep, getCotaCellDep(isMainnet)]
const rawTx = {
version: '0x0',
cellDeps,
headerDeps: [],
inputs,
outputs,
outputsData,
witnesses: [],
}
rawTx.witnesses = rawTx.inputs.map((_, i) =>
i > 0 ? '0x' : { lock: '', inputType: `0x08${transferUpdateSmtEntry}`, outputType: '' },
)
return rawTx
}
21 changes: 21 additions & 0 deletions src/types/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,27 @@ export interface UpdateReq extends SmtReq {
nfts: CotaNft[]
}

export interface ClaimUpdateReq extends SmtReq {
lockScript: Bytes
withdrawalLockHash: Byte32
nfts: CotaNft[]
}

export interface TransferUpdate {
cotaId: Byte20
tokenIndex: Byte4
toLockScript: Bytes
state: Byte
characteristic: Byte20
}

export interface TransferUpdateReq extends SmtReq {
lockScript: Bytes
withdrawalLockHash: CKBComponents.Hash
transferOutPoint: Byte24
transfers: TransferUpdate[]
}

export interface GetCotaReq extends SmtReq {
lockScript: Bytes
page: number
Expand Down
12 changes: 12 additions & 0 deletions src/types/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ export interface UpdateResp extends SmtResp {
blockNumber: bigint
}

export interface ClaimUpdateResp extends SmtResp {
smtRootHash: Byte32
claimUpdateSmtEntry: Bytes
blockNumber: bigint
}

export interface TransferUpdateResp extends SmtResp {
smtRootHash: Byte32
transferUpdateSmtEntry: Bytes
blockNumber: bigint
}

export interface GetHoldResp extends SmtResp {
total: number
pageSize: number
Expand Down
Loading

0 comments on commit 755886b

Please sign in to comment.