This repository was archived by the owner on May 27, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 22
Support RGB++ compatible xUDT assets #291
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
a996238
feat: Fetch compatible xudt cellDeps
duanyytop 4e462df
feat: Fetch compatible xudt cellDeps for RGB++ operations
duanyytop ee1175e
fix: Update some test case data
duanyytop 78afa04
fix: Update rgbpp package to transfer compatible xudt
duanyytop b02e17e
feat: Add compatible xUDT examples
duanyytop 5a778bb
tests: Add interation tests for compabile xUDT
duanyytop 8798609
feat: Add /assets/type api to btc service
duanyytop db92275
chore: Update assets-api example
duanyytop 56b960f
chore: Add changeset
duanyytop af8de22
refactor: Update btc-assets-api response data type
duanyytop eeb0d6a
Fix servie test error
duanyytop 60156be
test: Switching from Signet to Testnet3 for testing.
Dawn-githup 4d5afce
test: Fix the execution failure issue of 'compatible-xudt'.
Dawn-githup File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| --- | ||
| '@rgbpp-sdk/service': minor | ||
| 'rgbpp': minor | ||
| '@rgbpp-sdk/ckb': minor | ||
| --- | ||
|
|
||
| Support compatible xUDT RGB++ assets | ||
|
|
||
| - Fetch compatible xUDT `cellDeps` to build CKB transactions from the `typeid-contract-cell-deps` GitHub repository | ||
| - Update the `ckb` package to support RGB++ compatible xUDT assets leaping and transferring | ||
| - Add optional parameter `compatibleXudtTypeScript` to the functions of the `rgbpp` package to transfer RGB++ compatible xUDT assets | ||
| - Add RGB++ compatible xUDT assets leaping and transferring examples | ||
| - Add RGB++ compatible xUDT assets integration tests | ||
| - Add `assets/type` API to the service package |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import { serializeScript } from '@nervosnetwork/ckb-sdk-utils'; | ||
| import { genCkbJumpBtcVirtualTx } from 'rgbpp'; | ||
| import { getSecp256k1CellDep, buildRgbppLockArgs } from 'rgbpp/ckb'; | ||
| import { CKB_PRIVATE_KEY, isMainnet, collector, ckbAddress, BTC_TESTNET_TYPE } from '../../env'; | ||
|
|
||
| interface LeapToBtcParams { | ||
| outIndex: number; | ||
| btcTxId: string; | ||
| transferAmount: bigint; | ||
| compatibleXudtTypeScript: CKBComponents.Script; | ||
| } | ||
|
|
||
| const leapRusdFromCkbToBtc = async ({ | ||
| outIndex, | ||
| btcTxId, | ||
| transferAmount, | ||
| compatibleXudtTypeScript, | ||
| }: LeapToBtcParams) => { | ||
| const toRgbppLockArgs = buildRgbppLockArgs(outIndex, btcTxId); | ||
|
|
||
| const ckbRawTx = await genCkbJumpBtcVirtualTx({ | ||
| collector, | ||
| fromCkbAddress: ckbAddress, | ||
| toRgbppLockArgs, | ||
| xudtTypeBytes: serializeScript(compatibleXudtTypeScript), | ||
| transferAmount, | ||
| btcTestnetType: BTC_TESTNET_TYPE, | ||
| }); | ||
|
|
||
| const emptyWitness = { lock: '', inputType: '', outputType: '' }; | ||
| const unsignedTx: CKBComponents.RawTransactionToSign = { | ||
| ...ckbRawTx, | ||
| cellDeps: [...ckbRawTx.cellDeps, getSecp256k1CellDep(isMainnet)], | ||
| witnesses: [emptyWitness, ...ckbRawTx.witnesses.slice(1)], | ||
| }; | ||
|
|
||
| const signedTx = collector.getCkb().signTransaction(CKB_PRIVATE_KEY)(unsignedTx); | ||
|
|
||
| const txHash = await collector.getCkb().rpc.sendTransaction(signedTx, 'passthrough'); | ||
| console.info(`Rgbpp compatible xUDT asset has been leaped from CKB to BTC and CKB tx hash is ${txHash}`); | ||
| }; | ||
|
|
||
| // Please use your real BTC UTXO information on the BTC Testnet | ||
| // BTC Testnet3: https://mempool.space/testnet | ||
| // BTC Signet: https://mempool.space/signet | ||
| leapRusdFromCkbToBtc({ | ||
| outIndex: 4, | ||
| btcTxId: '44de1b4e3ddaa95cc85cc8b1c60f3e439d343002f0c60980fb4c70841ee0c75e', | ||
| // Please use your own RGB++ compatible xUDT asset's type script | ||
| compatibleXudtTypeScript: { | ||
| codeHash: '0x1142755a044bf2ee358cba9f2da187ce928c91cd4dc8692ded0337efa677d21a', | ||
| hashType: 'type', | ||
| args: '0x878fcc6f1f08d48e87bb1c3b3d5083f23f8a39c5d5c764f253b55b998526439b', | ||
| }, | ||
| transferAmount: BigInt(1000_0000), | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| import { buildRgbppLockArgs } from 'rgbpp/ckb'; | ||
| import { buildRgbppTransferTx } from 'rgbpp'; | ||
| import { isMainnet, collector, btcService, btcAccount, btcDataSource, BTC_TESTNET_TYPE } from '../../env'; | ||
| import { saveCkbVirtualTxResult } from '../../shared/utils'; | ||
| import { signAndSendPsbt } from '../../shared/btc-account'; | ||
| import { bitcoin } from 'rgbpp/btc'; | ||
|
|
||
| interface RgbppTransferParams { | ||
| rgbppLockArgsList: string[]; | ||
| toBtcAddress: string; | ||
| transferAmount: bigint; | ||
| compatibleXudtTypeScript: CKBComponents.Script; | ||
| } | ||
|
|
||
| const transferRusdOnBtc = async ({ | ||
| rgbppLockArgsList, | ||
| toBtcAddress, | ||
| compatibleXudtTypeScript, | ||
| transferAmount, | ||
| }: RgbppTransferParams) => { | ||
| const { ckbVirtualTxResult, btcPsbtHex } = await buildRgbppTransferTx({ | ||
| ckb: { | ||
| collector, | ||
| xudtTypeArgs: compatibleXudtTypeScript.args, | ||
| rgbppLockArgsList, | ||
| transferAmount, | ||
| compatibleXudtTypeScript, | ||
| }, | ||
| btc: { | ||
| fromAddress: btcAccount.from, | ||
| toAddress: toBtcAddress, | ||
| fromPubkey: btcAccount.fromPubkey, | ||
| dataSource: btcDataSource, | ||
| testnetType: BTC_TESTNET_TYPE, | ||
| }, | ||
| isMainnet, | ||
| }); | ||
|
|
||
| // Save ckbVirtualTxResult | ||
| saveCkbVirtualTxResult(ckbVirtualTxResult, '2-btc-transfer'); | ||
|
|
||
| // Send BTC tx | ||
| const psbt = bitcoin.Psbt.fromHex(btcPsbtHex); | ||
| const { txId: btcTxId } = await signAndSendPsbt(psbt, btcAccount, btcService); | ||
| console.log(`BTC ${BTC_TESTNET_TYPE} TxId: ${btcTxId}`); | ||
|
|
||
| await btcService.sendRgbppCkbTransaction({ btc_txid: btcTxId, ckb_virtual_result: ckbVirtualTxResult }); | ||
|
|
||
| try { | ||
| const interval = setInterval(async () => { | ||
| const { state, failedReason } = await btcService.getRgbppTransactionState(btcTxId); | ||
| console.log('state', state); | ||
| if (state === 'completed' || state === 'failed') { | ||
| clearInterval(interval); | ||
| if (state === 'completed') { | ||
| const { txhash: txHash } = await btcService.getRgbppTransactionHash(btcTxId); | ||
| console.info( | ||
| `Rgbpp compatible xUDT asset has been transferred on BTC and the related CKB tx hash is ${txHash}`, | ||
| ); | ||
| } else { | ||
| console.warn(`Rgbpp CKB transaction failed and the reason is ${failedReason} `); | ||
| } | ||
| } | ||
| }, 30 * 1000); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
|
|
||
| // Please use your real BTC UTXO information on the BTC Testnet | ||
| // BTC Testnet3: https://mempool.space/testnet | ||
| // BTC Signet: https://mempool.space/signet | ||
|
|
||
| // rgbppLockArgs: outIndexU32 + btcTxId | ||
| transferRusdOnBtc({ | ||
| rgbppLockArgsList: [buildRgbppLockArgs(4, '44de1b4e3ddaa95cc85cc8b1c60f3e439d343002f0c60980fb4c70841ee0c75e')], | ||
| toBtcAddress: 'tb1qvt7p9g6mw70sealdewtfp0sekquxuru6j3gwmt', | ||
| // Please use your own RGB++ compatible xudt asset's type script | ||
| compatibleXudtTypeScript: { | ||
| codeHash: '0x1142755a044bf2ee358cba9f2da187ce928c91cd4dc8692ded0337efa677d21a', | ||
| hashType: 'type', | ||
| args: '0x878fcc6f1f08d48e87bb1c3b3d5083f23f8a39c5d5c764f253b55b998526439b', | ||
| }, | ||
| transferAmount: BigInt(100_0000), | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| import { buildRgbppLockArgs } from 'rgbpp/ckb'; | ||
| import { serializeScript } from '@nervosnetwork/ckb-sdk-utils'; | ||
| import { genBtcJumpCkbVirtualTx, sendRgbppUtxos } from 'rgbpp'; | ||
| import { isMainnet, collector, btcService, btcDataSource, btcAccount, BTC_TESTNET_TYPE } from '../../env'; | ||
| import { saveCkbVirtualTxResult } from '../../shared/utils'; | ||
| import { signAndSendPsbt } from '../../shared/btc-account'; | ||
|
|
||
| interface LeapToCkbParams { | ||
| rgbppLockArgsList: string[]; | ||
| toCkbAddress: string; | ||
| transferAmount: bigint; | ||
| compatibleXudtTypeScript: CKBComponents.Script; | ||
| } | ||
|
|
||
| const leapRusdFromBtcToCKB = async ({ | ||
| rgbppLockArgsList, | ||
| toCkbAddress, | ||
| compatibleXudtTypeScript, | ||
| transferAmount, | ||
| }: LeapToCkbParams) => { | ||
| const ckbVirtualTxResult = await genBtcJumpCkbVirtualTx({ | ||
| collector, | ||
| rgbppLockArgsList, | ||
| xudtTypeBytes: serializeScript(compatibleXudtTypeScript), | ||
| transferAmount, | ||
| toCkbAddress, | ||
| isMainnet, | ||
| btcTestnetType: BTC_TESTNET_TYPE, | ||
| // btcConfirmationBlocks: 20, // default value is 6 | ||
| }); | ||
|
|
||
| // Save ckbVirtualTxResult | ||
| saveCkbVirtualTxResult(ckbVirtualTxResult, '3-btc-leap-ckb'); | ||
|
|
||
| const { commitment, ckbRawTx } = ckbVirtualTxResult; | ||
|
|
||
| // Send BTC tx | ||
| const psbt = await sendRgbppUtxos({ | ||
| ckbVirtualTx: ckbRawTx, | ||
| commitment, | ||
| tos: [btcAccount.from], | ||
| ckbCollector: collector, | ||
| from: btcAccount.from, | ||
| fromPubkey: btcAccount.fromPubkey, | ||
| source: btcDataSource, | ||
| }); | ||
|
|
||
| const { txId: btcTxId } = await signAndSendPsbt(psbt, btcAccount, btcService); | ||
| console.log(`BTC ${BTC_TESTNET_TYPE} TxId: ${btcTxId}`); | ||
|
|
||
| await btcService.sendRgbppCkbTransaction({ btc_txid: btcTxId, ckb_virtual_result: ckbVirtualTxResult }); | ||
|
|
||
| try { | ||
| const interval = setInterval(async () => { | ||
| const { state, failedReason } = await btcService.getRgbppTransactionState(btcTxId); | ||
| console.log('state', state); | ||
| if (state === 'completed' || state === 'failed') { | ||
| clearInterval(interval); | ||
| if (state === 'completed') { | ||
| const { txhash: txHash } = await btcService.getRgbppTransactionHash(btcTxId); | ||
| console.info( | ||
| `Rgbpp compatible xUDT asset has been leaped from BTC to CKB and the related CKB tx hash is ${txHash}`, | ||
| ); | ||
| } else { | ||
| console.warn(`Rgbpp CKB transaction failed and the reason is ${failedReason} `); | ||
| } | ||
| } | ||
| }, 30 * 1000); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
|
|
||
| // Please use your real BTC UTXO information on the BTC Testnet | ||
| // BTC Testnet3: https://mempool.space/testnet | ||
| // BTC Signet: https://mempool.space/signet | ||
|
|
||
| // rgbppLockArgs: outIndexU32 + btcTxId | ||
| leapRusdFromBtcToCKB({ | ||
| rgbppLockArgsList: [buildRgbppLockArgs(1, '58ebbdec0dfd464280658e36fadc11c41945de2c4b5b59463dad6e045a7e5faf')], | ||
| toCkbAddress: 'ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsq0e4xk4rmg5jdkn8aams492a7jlg73ue0gc0ddfj', | ||
| // Please use your own RGB++ compatible xudt asset's type script | ||
| compatibleXudtTypeScript: { | ||
| codeHash: '0x1142755a044bf2ee358cba9f2da187ce928c91cd4dc8692ded0337efa677d21a', | ||
| hashType: 'type', | ||
| args: '0x878fcc6f1f08d48e87bb1c3b3d5083f23f8a39c5d5c764f253b55b998526439b', | ||
| }, | ||
| transferAmount: BigInt(100_0000), | ||
| }); |
42 changes: 42 additions & 0 deletions
42
examples/rgbpp/xudt/compatible-xudt/4-unlock-btc-time-cell.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { buildBtcTimeCellsSpentTx, signBtcTimeCellSpentTx } from 'rgbpp'; | ||
| import { sendCkbTx, getBtcTimeLockScript } from 'rgbpp/ckb'; | ||
| import { BTC_TESTNET_TYPE, CKB_PRIVATE_KEY, btcService, ckbAddress, collector, isMainnet } from '../../env'; | ||
|
|
||
| // Warning: Wait at least 6 BTC confirmation blocks to spend the BTC time cells after 3-btc-leap-ckb.ts | ||
| const unlockRusdBtcTimeCell = async ({ btcTimeCellArgs }: { btcTimeCellArgs: string }) => { | ||
| const btcTimeCells = await collector.getCells({ | ||
| lock: { | ||
| ...getBtcTimeLockScript(isMainnet, BTC_TESTNET_TYPE), | ||
| args: btcTimeCellArgs, | ||
| }, | ||
| isDataMustBeEmpty: false, | ||
| }); | ||
|
|
||
| if (!btcTimeCells || btcTimeCells.length === 0) { | ||
| throw new Error('No btc time cell found'); | ||
| } | ||
|
|
||
| const ckbRawTx: CKBComponents.RawTransaction = await buildBtcTimeCellsSpentTx({ | ||
| btcTimeCells, | ||
| btcAssetsApi: btcService, | ||
| isMainnet, | ||
| btcTestnetType: BTC_TESTNET_TYPE, | ||
| }); | ||
|
|
||
| const signedTx = await signBtcTimeCellSpentTx({ | ||
| secp256k1PrivateKey: CKB_PRIVATE_KEY, | ||
| collector, | ||
| masterCkbAddress: ckbAddress, | ||
| ckbRawTx, | ||
| isMainnet, | ||
| }); | ||
|
|
||
| const txHash = await sendCkbTx({ collector, signedTx }); | ||
| console.info(`BTC time cell has been spent and CKB tx hash is ${txHash}`); | ||
| }; | ||
|
|
||
| // The btcTimeCellArgs is from the outputs[0].lock.args(BTC Time lock args) of the 3-btc-leap-ckb.ts CKB transaction | ||
| unlockRusdBtcTimeCell({ | ||
| btcTimeCellArgs: | ||
| '0x7d00000010000000590000005d000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce80114000000f9a9ad51ed14936d33f7bb854aaefa5f47a3ccbd0600000038036f35121682517b5f79732fc6a182e0050cfe1ad4cce0a1314c229a1ba364', | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import { serializeScript } from '@nervosnetwork/ckb-sdk-utils'; | ||
| import { btcService } from '../../env'; | ||
|
|
||
| (async () => { | ||
| const assets = await btcService.getRgbppAssetsByBtcAddress('tb1qvt7p9g6mw70sealdewtfp0sekquxuru6j3gwmt', { | ||
| type_script: serializeScript({ | ||
| codeHash: '0x1142755a044bf2ee358cba9f2da187ce928c91cd4dc8692ded0337efa677d21a', | ||
| hashType: 'type', | ||
| args: '0x878fcc6f1f08d48e87bb1c3b3d5083f23f8a39c5d5c764f253b55b998526439b', | ||
| }), | ||
| }); | ||
| console.log('RUSD Assets: ', JSON.stringify(assets)); | ||
|
|
||
| const activities = await btcService.getRgbppActivityByBtcAddress('tb1qvt7p9g6mw70sealdewtfp0sekquxuru6j3gwmt', { | ||
| type_script: serializeScript({ | ||
| codeHash: '0x1142755a044bf2ee358cba9f2da187ce928c91cd4dc8692ded0337efa677d21a', | ||
| hashType: 'type', | ||
| args: '0x878fcc6f1f08d48e87bb1c3b3d5083f23f8a39c5d5c764f253b55b998526439b', | ||
| }), | ||
| }); | ||
| console.log('RUSD Activities: ', JSON.stringify(activities)); | ||
|
|
||
| const info = await btcService.getRgbppAssetInfoByTypeScript( | ||
| serializeScript({ | ||
| codeHash: '0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb', | ||
| hashType: 'type', | ||
| args: '0x661cfbe2124b3e79e50e505c406be5b2dcf9da15d8654b749ec536fa4c2eaaae', | ||
| }), | ||
| ); | ||
| console.log('Standard xUDT info: ', JSON.stringify(info)); | ||
| })(); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.