Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(deps): update rgbpp-sdk #15

Merged
merged 7 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^3.0.0",
"@nervosnetwork/ckb-sdk-utils": "^0.109.1",
"@rgbpp-sdk/btc": "0.0.0-snap-20240326062949",
"@rgbpp-sdk/ckb": "0.0.0-snap-20240326062949",
"@rgbpp-sdk/btc": "0.0.0-snap-20240327091939",
"@rgbpp-sdk/ckb": "0.0.0-snap-20240327091939",
"@rgbpp-sdk/service": "0.0.0-snap-20240327091939",
"@sentry/node": "^7.102.1",
"@sentry/profiling-node": "^7.102.1",
"awilix": "^10.0.1",
Expand Down
73 changes: 59 additions & 14 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions src/routes/rgbpp/spv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ const spvRoute: FastifyPluginCallback<Record<never, never>, Server, ZodTypeProvi
async (request, reply) => {
try {
const { txid, confirmations } = request.query;
const btcTx = await fastify.electrs.getTransaction(txid);
const txids = await fastify.electrs.getBlockTxIdsByHash(btcTx.status.block_hash!);
const index = txids.findIndex((id) => id === txid);
const proof = await fastify.bitcoinSPV.getTxProof(txid, index, confirmations);
const proof = await fastify.bitcoinSPV.getTxProof(txid, confirmations);
if (proof) {
reply.header(CUSTOM_HEADERS.ResponseCacheable, 'true');
}
Expand Down
7 changes: 7 additions & 0 deletions src/routes/rgbpp/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ const transactionRoute: FastifyPluginCallback<Record<never, never>, Server, ZodT
response: {
200: z.object({
state: z.string().describe('The state of the transaction'),
failedReason: z.string().optional().describe('The reason why the transaction failed'),
}),
},
},
Expand All @@ -130,6 +131,12 @@ const transactionRoute: FastifyPluginCallback<Record<never, never>, Server, ZodT
return;
}
const state = await job.getState();
if (state === 'failed') {
return {
state,
failedReason: job.failedReason,
};
}
return { state };
},
);
Expand Down
18 changes: 14 additions & 4 deletions src/services/spv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ export class BitcoinSPVError extends Error {
*/
export default class BitcoinSPV {
private request: AxiosInstance;
private cradle: Cradle;

constructor({ env, logger }: Cradle) {
const { BITCOIN_SPV_SERVICE_URL } = env;
constructor(cradle: Cradle) {
const { env, logger } = cradle;
this.cradle = cradle;
this.request = axios.create({
baseURL: BITCOIN_SPV_SERVICE_URL,
baseURL: env.BITCOIN_SPV_SERVICE_URL,
});
addLoggerInterceptor(this.request, logger);
}
Expand All @@ -72,7 +74,15 @@ export default class BitcoinSPV {
}

// https://github.com/ckb-cell/ckb-bitcoin-spv-service?tab=readme-ov-file#json-rpc-api-reference
public async getTxProof(txid: string, index: number, confirmations: number) {
private async _getTxProof(txid: string, index: number, confirmations: number) {
return this.callMethod<TxProof>('getTxProof', [remove0x(txid), index, confirmations]);
}

public async getTxProof(btcTxid: string, confirmations: number = 0) {
const txid = remove0x(btcTxid);
const btcTx = await this.cradle.electrs.getTransaction(txid);
const btcTxids = await this.cradle.electrs.getBlockTxIdsByHash(btcTx.status.block_hash!);
const btcIdxInBlock = btcTxids.findIndex((id) => id === txid);
return this._getTxProof(txid, btcIdxInBlock, confirmations);
}
}
52 changes: 25 additions & 27 deletions src/services/transaction.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import { Cradle } from '../container';
import { DelayedError, Job, Queue, Worker } from 'bullmq';
import { AxiosError } from 'axios';
import { CKBRawTransaction, CKBVirtualResult } from '../routes/rgbpp/types';
import { opReturnScriptPubKeyToData, transactionToHex } from '@rgbpp-sdk/btc';
import { bytes } from '@ckb-lumos/codec';
import { opReturnScriptPubKeyToData, remove0x, transactionToHex } from '@rgbpp-sdk/btc';
import {
appendCkbTxWitnesses,
SPVService,
sendCkbTx,
BTCTimeLock,
BTC_JUMP_CONFIRMATION_BLOCKS,
Collector,
append0x,
RGBPPLock,
updateCkbTxWithRealBtcTxId,
RGBPP_TX_ID_PLACEHOLDER,
SpvRpcError,
BTCTimeLock,
append0x,
appendCkbTxWitnesses,
getBtcTimeLockScript,
RGBPP_TX_ID_PLACEHOLDER,
getRgbppLockScript,
BTC_JUMP_CONFIRMATION_BLOCKS,
sendCkbTx,
updateCkbTxWithRealBtcTxId,
} from '@rgbpp-sdk/ckb';
import {
btcTxIdFromBtcTimeLockArgs,
Expand All @@ -27,9 +23,12 @@ import {
lockScriptFromBtcTimeLockArgs,
} from '@rgbpp-sdk/ckb/lib/utils/rgbpp';
import * as Sentry from '@sentry/node';
import { Transaction } from '../routes/bitcoin/types';
import { bytes } from '@ckb-lumos/codec';
import { AxiosError } from 'axios';
import { Transaction as BitcoinTransaction } from 'bitcoinjs-lib';
import { DelayedError, Job, Queue, Worker } from 'bullmq';
import { Cradle } from '../container';
import { Transaction } from '../routes/bitcoin/types';
import { CKBRawTransaction, CKBVirtualResult } from '../routes/rgbpp/types';

export interface ITransactionRequest {
txid: string;
Expand Down Expand Up @@ -83,7 +82,6 @@ export default class TransactionManager implements ITransactionManager {
private cradle: Cradle;
private queue: Queue<ITransactionRequest>;
private worker: Worker<ITransactionRequest>;
private spvService: SPVService;

constructor(cradle: Cradle) {
this.cradle = cradle;
Expand All @@ -103,7 +101,6 @@ export default class TransactionManager implements ITransactionManager {
autorun: false,
concurrency: 10,
});
this.spvService = new SPVService(cradle.env.BITCOIN_SPV_SERVICE_URL);
}

private get isMainnet() {
Expand Down Expand Up @@ -152,7 +149,7 @@ export default class TransactionManager implements ITransactionManager {
const unpack = RGBPPLock.unpack(lock.args);
// https://github.com/ckb-cell/rgbpp-sdk/tree/main/examples/rgbpp#what-you-must-know-about-btc-transaction-id
const btcTxid = bytes.hexify(bytes.bytify(unpack.btcTxid).reverse());
if (btcTxid !== append0x(txid)) {
if (remove0x(btcTxid) !== txid) {
return output;
}
return {
Expand All @@ -162,7 +159,7 @@ export default class TransactionManager implements ITransactionManager {
}
if (this.isBtcTimeLock(lock)) {
const btcTxid = btcTxIdFromBtcTimeLockArgs(lock.args);
if (btcTxid !== append0x(txid)) {
if (remove0x(btcTxid) !== txid) {
return output;
}
const toLock = lockScriptFromBtcTimeLockArgs(lock.args);
Expand Down Expand Up @@ -258,18 +255,22 @@ export default class TransactionManager implements ITransactionManager {
const needUpdateCkbTx = ckbRawTx.outputs.some((output) => {
if (this.isRgbppLock(output.lock)) {
const { btcTxid } = RGBPPLock.unpack(output.lock.args);
const txid = remove0x(btcTxid);
this.cradle.logger.debug(`[TransactionManager] RGBPP_LOCK args txid: ${btcTxid}`);
return (
output.lock.codeHash === this.rgbppLockScript.codeHash &&
output.lock.hashType === this.rgbppLockScript.hashType &&
btcTxid === RGBPP_TX_ID_PLACEHOLDER
txid === RGBPP_TX_ID_PLACEHOLDER
);
}
if (this.isBtcTimeLock(output.lock)) {
const { btcTxid, after } = BTCTimeLock.unpack(output.lock.args);
const txid = remove0x(btcTxid);
this.cradle.logger.debug(`[TransactionManager] BTC_TIME_LOCK args txid: ${txid}`);
return (
output.lock.codeHash === this.btcTimeLockScript.codeHash &&
output.lock.hashType === this.btcTimeLockScript.hashType &&
btcTxid === RGBPP_TX_ID_PLACEHOLDER &&
txid === RGBPP_TX_ID_PLACEHOLDER &&
after === BTC_JUMP_CONFIRMATION_BLOCKS
);
}
Expand Down Expand Up @@ -304,19 +305,16 @@ export default class TransactionManager implements ITransactionManager {
const ckbRawTx = this.getCkbRawTxWithRealBtcTxid(ckbVirtualResult, txid);
// bitcoin JSON-RPC gettransaction is wallet only
// we need to use electrs to get the transaction hex and index in block
const [hex, btcTxIndexInBlock] = await Promise.all([
const [hex, rgbppApiSpvProof] = await Promise.all([
this.cradle.electrs.getTransactionHex(txid),
this.cradle.electrs.getBlockTxIdsByHash(btcTx.status.block_hash!).then((txids) => txids.indexOf(txid)),
this.cradle.bitcoinSPV.getTxProof(txid),
]);
// using for spv proof, we need to remove the witness data from the transaction
const hexWithoutWitness = transactionToHex(BitcoinTransaction.fromHex(hex), false);
let signedTx = await appendCkbTxWitnesses({
...ckbVirtualResult,
ckbRawTx,
spvService: this.spvService,
btcTxId: txid,
btcTxBytes: hexWithoutWitness,
btcTxIndexInBlock,
rgbppApiSpvProof,
})!;

// append paymaster cell and sign the transaction if needed
Expand Down
Loading
Loading